IOS 多线程编程指南_GCD

来源:互联网 发布:淘宝潮男店铺粉丝排行 编辑:程序博客网 时间:2024/05/16 05:29
  1. dispatch_apply
    简介:功能:把一项任务提交到队列中多次执行,具体是并行执行还是串行执行由队列本身决定.注意,dispatch_apply不会立刻返回,在执行完毕后才会返回,是同步的调用。
    iterations 执行的次数
    queue 提交到的队列
    block 执行的任务

dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));

应用举例1>
比如我有一个数组,存储了一系列对象,初始化的时候,这些对象都要调用一次某函数来进行相关的计算。这些计算相互没有影响。这时,我们就可以用dispatch_apply来使用异步队列来初始化.这里把这种情况进行简化

    NSMutableArray* muarray = [@[@"hello",@"hellolcg",@"goodbay lms"]mutableCopy];    dispatch_apply(3,dispatch_get_global_queue(0,0),^(size_t time){        NSLog(@"str=%@",muarray[time]);    });    NSLog(@"Dispatch_after in global queue is over");

dispatch_get_global_queue 为全局的并发队列,执行顺序是不确定的,size_t time 的数值必须小于数组数量,否则会越界崩溃
dispath_apply是同步执行的,所以只有数组打印完之后才会执行
NSLog(@”Dispatch_after in global queue is over”);

这里写图片描述

由于同步执行会导致线程阻塞,所以做了以下改进

    dispatch_async(dispatch_get_global_queue(0, 0), ^{        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            NSLog(@"ssssssssssssss");        });        NSLog(@"Dispatch_after in global queue is over");    });

应用举例2>

- (IBAction)clicked:(id)sender{    // 控制代码块执行5次    dispatch_apply(5        , dispatch_get_global_queue(0, 0)        // time形参代表当前正在执行第几次        , ^(size_t time)        {            NSLog(@"===执行【%lu】次===%@" , time                , [NSThread currentThread]);        });}

这里写图片描述
这里并发执行第五次打印,但不一定是并发了五个线程,可能是由系统资源确定的

2.dispatch_after
功能:延迟一段时间把一项任务提交到队列中执行,返回之后就不能取消
常用来在在主队列上延迟执行一项任务
函数原型
dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
参数
when 过了多久执行的时间间隔
queue 提交到的队列
block 执行的任务

例如:可以利用dispatch_after写一个自己用的Delay函数,delay一段时间在主线程上执行一段代码

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{        NSLog(@"ssssssssssssss");    });

应用举例1>
比如,当用户的应用不满足某些我们App需要的条件时候(例如,我们的App需要蓝牙打开),然后在APP启动的时候测到蓝牙Off后,应当给用户一个提示。在view载入完成后,延迟给用户一个提示,也可以给这个提示添加一些动画,要比view在载入完成直接显示提示要有好的多。
举例
在viewLoad后,延迟1s,提示一个alertview

class ViewController: UIViewController{        func hwcDelay(delay:Double, closure:()->()) {    dispatch_after(        dispatch_time(            DISPATCH_TIME_NOW,            Int64(delay * Double(NSEC_PER_SEC))        ),        dispatch_get_main_queue(), closure)}      override func viewDidLoad(){            super.viewDidLoad()            hwcDelay(1.0){        var alertview = UIAlertView(title:"Dispatch_after",message:"Message",delegate:self,cancelButtonTitle:"OK")        alertview.show()    }              }        override func didReceiveMemoryWarning(){            super.didReceiveMemoryWarning()        }    } 

3.dispatch_once
功能:保证在APP运行期间,block中的代码只执行一次
在生成单例的经常使用

当然也可以在多线程环境下,保证一段代码只执行一次。

+ (instancetype)sharedInstance {    static id sharedInstance = nil;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedInstance = [[self alloc] init];    });    return sharedInstance;}

单例或许你不太明白,下面写一个按钮,无论点击多少次
NSLog输出只会执行一次

- (IBAction)clicked:(id)sender{       static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        NSLog(@"==执行代码块==");        // 线程暂停3秒        [NSThread sleepForTimeInterval:3];    });}

4.dispatch_sync()
同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行

- (IBAction)clicked:(id)sender{    // 以同步方式先后提交2个代码块    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)        , ^(void){            for (int i = 0 ; i < 100; i ++)            {                NSLog(@"%@=====%d"  , [NSThread currentThread] , i);                [NSThread sleepForTimeInterval:0.1];            }        });    // 必须等第一次提交的代码块执行完成后,dispatch_sync()函数才会返回,    // 程序才会执行到这里,才能提交第二个代码块。    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)        , ^(void){            for (int i = 0 ; i < 100; i ++)            {                NSLog(@"%@-----%d"  , [NSThread currentThread] , i);                [NSThread sleepForTimeInterval:0.1];            }        });}

5.dispatch_async ,异步添加进任务队列,它不会做任何等待

 dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);    NSLog(@"1");    dispatch_async(concurrentQueue, ^(){        NSLog(@"2");        [NSThread sleepForTimeInterval:5];        NSLog(@"3");    });    NSLog(@"4");

这里写图片描述

6.dispatch_queue_t

GCD队列
dispatch_queue_t disQueue =dispatch_queue_create(“队列1”, 0);

下面展示的是三种获得主线程队列的方式:
NSThread
GCD
NSOperationQueue

-(void)press{dispatch_queue_t _disQueue=dispatch_queue_create("队列1", 0);    [self startDisPath];    [self runMainByThread];    [self runMainByDisPath];    [self runMainByOpration];}
-(void)startDisPath{    dispatch_queue_t global=_disQueue;    dispatch_async(global, ^                   {                       NSLog(@"=====current==%@", [NSThread  currentThread]);                   });}-(void)runMainByThread{    [NSThread detachNewThreadSelector:@selector(update01) toTarget:self withObject:nil];}-(void)update01{    while (true) {        static int i=0;        i++;        NSThread*main=[NSThread mainThread];        [self performSelector:@selector(updateMain) onThread:main withObject:nil waitUntilDone:YES];        if (i==1001)        {            [NSThread exit];        }    }}-(void)updateMain{    NSLog(@"在主线程中进行");}-(void)runMainByOpration{    //获得主线程队列    NSOperationQueue*mainQueue=[NSOperationQueue mainQueue];    [mainQueue addOperationWithBlock:^{        NSLog(@"=====current==%@", [NSThread  currentThread]);        //在主线程中使用 updateMian        [self updateMain];    }];}-(void)runMainByDisPath{    dispatch_queue_t mainDis=dispatch_get_main_queue();    //    dispatch_async(mainDis, ^{        NSLog(@"=====current==%@", [NSThread  currentThread]);        [self updateMain];    });}

这里写图片描述

另外一个例子,GCD如何创建一个串行队列和并发队列?

@implementation FKViewController// 定义2个队列dispatch_queue_t serialQueue;dispatch_queue_t concurrentQueue;- (void)viewDidLoad{    [super viewDidLoad];    // 创建串行队列    serialQueue = dispatch_queue_create("fkjava.queue", DISPATCH_QUEUE_SERIAL);    // 创建并发队列    concurrentQueue = dispatch_queue_create("fkjava.queue"        , DISPATCH_QUEUE_CONCURRENT);}- (IBAction)serial:(id)sender{    // 依次将2个代码块提交给串行队列    // 必须等到第1个代码块完成后,才能执行第2个代码块。    dispatch_async(serialQueue, ^(void)    {        for (int i = 0 ; i < 100; i ++)        {            NSLog(@"%@=====%d"  , [NSThread currentThread] , i);        }    });    dispatch_async(serialQueue, ^(void)    {        for (int i = 0 ; i < 100; i ++)        {            NSLog(@"%@------%d" , [NSThread currentThread] , i);        }    });}- (IBAction)concurrent:(id)sender{    // 依次将2个代码块提交给并发队列    // 两个代码块可以并发执行    dispatch_async(concurrentQueue, ^(void)    {        for (int i = 0 ; i < 100; i ++)        {            NSLog(@"%@=====%d"  , [NSThread currentThread] , i);        }    });    dispatch_async(concurrentQueue, ^(void)    {        for (int i = 0 ; i < 100; i ++)        {            NSLog(@"%@------%d" , [NSThread currentThread] , i);        }    });}@end

参考来源:
http://write.blog.csdn.net/mdeditor

关于介绍GCD一篇比较好的博客(文顶顶)
http://www.cnblogs.com/wendingding/p/3806821.html

0 0
原创粉丝点击