CGD

CGD常见的几种用法

Posted by zfx5130 on August 8, 2017

基础

//全局队列,一个并行的队列
dispatch_get_global_queue
//主队列,主线程中的唯一队列,一个串行队列
dispatch_get_main_queue

//同步线程
dispatch_sync(..., ^(block))
//异步线程
dispatch_async(..., ^(block))

1.异步提交,主线程更新UI。

- (void)viewDidLoad {
	[super viewDidLoad];
    //将工作从主线程转移到全局队列中,这是dispatch_async调用,异步提交保证调用线程会继续执行下去,这样viewDidLoad在主线程上能够更早完成。
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗时的操作
        dispatch_async(dispatch_get_main_queue(), ^{
		//主线程更新UI
        });
    });
}

2.栅栏函数,任务障碍

- (void)dispatchBarrierAsyncDemo {
    //防止文件读写冲突,可以创建一个串行队列,操作都在这个队列中进行,没有更新数据读用并行,写用串行。
    dispatch_queue_t dataQueue = dispatch_queue_create("com.starming.gcddemo.dataqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(dataQueue, ^{
        [NSThread sleepForTimeInterval:2.f];
        NSLog(@"read data 1");
    });
    dispatch_async(dataQueue, ^{
        NSLog(@"read data 2");
    });
    //等待前面的都完成,在执行barrier后面的
    dispatch_barrier_async(dataQueue, ^{
        NSLog(@"write data 1");
        //栅栏函数, 任务1和任务2,任务3和任务4 是并行处理。
        [NSThread sleepForTimeInterval:1];
    });
    dispatch_async(dataQueue, ^{
        [NSThread sleepForTimeInterval:1.f];
        NSLog(@"read data 3");
    });
    dispatch_async(dataQueue, ^{
        NSLog(@"read data 4");
    });
}

3.GCD同步若干个异步调用

- (void)gcd_async_queue_call {
    //创建队列组
    dispatch_group_t group = dispatch_group_create();
    //获取全局并发队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_async(group, queue, ^{
        //加载请求
        NSLog(@"1");
    });
    dispatch_group_async(group, queue, ^{
        //加载请求
        NSLog(@"2");
    });
    dispatch_group_async(group, queue, ^{
       //加载请求
        NSLog(@"3");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
       //合并请求操作处理
        NSLog(@"4");
    });
    //1.2.3并发,4合并请求
}

4.dispatch_once用法

+ (UIColor *)boringColor {
     static UIColor *color;
     //只运行一次
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
          color = [UIColor colorWithRed:0.380f green:0.376f blue:0.376f alpha:1.000f];
     });
     return color;
}

5.CGD延迟

- (void)cgd_after_handle {
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        //[self updateUi];
    });
}

6.dispatch_apply进行快速迭代

//因为可以并行执行,所以使用dispatch_apply可以运行的更快
- (void)dispatchApplyDemo {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_apply(10, concurrentQueue, ^(size_t i) {
        NSLog(@"%zu",i);
    });
    NSLog(@"The end"); //这里有个需要注意的是,dispatch_apply这个是会阻塞主线程的。这个log打印会在dispatch_apply都结束后才开始执行
}

//dispatch_apply能避免线程爆炸,因为GCD会管理并发
- (void)dealWiththreadWithMaybeExplode:(BOOL)explode {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue",DISPATCH_QUEUE_CONCURRENT);
    if (explode) {
        //有问题的情况,可能会死锁
        for (int i = 0; i < 999 ; i++) {
            dispatch_async(concurrentQueue, ^{
                NSLog(@"wrong %d",i);
                //do something hard
            });
        }
    } else {
        //会优化很多,能够利用GCD管理
        dispatch_apply(999, concurrentQueue, ^(size_t i){
            NSLog(@"correct %zu",i);
            //do something hard
        });
    }
}

//实例1:
- (void)groupSync {
    //当调用enter时计数加1,调用leave时计数减1,当计数为0时会调用dispatch_group_notify并且dispatch_group_wait会停止等待;
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(5);
        NSLog(@"任务一完成"); dispatch_group_leave(group);
    });
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(8);
        NSLog(@"任务二完成"); dispatch_group_leave(group);
    });
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任务完成");
    });
}

7.dispatch_group_notify & dispatch_group_wait

//dispatch_group_notify
- (void)dispatchGroupNotifyDemo {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue",DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, concurrentQueue, ^{
        NSLog(@"--1");
    });
    dispatch_group_async(group, concurrentQueue, ^{
        NSLog(@"--2");
    });
    //最后执行
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"end");
    });
    NSLog(@"can continue");
}

//dispatch_group_wait
- (void)dispatchGroupWaitDemo {
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue",DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    //在group中添加队列的block
    dispatch_group_async(group, concurrentQueue, ^{
        [NSThread sleepForTimeInterval:5.f];
        NSLog(@"1");
    });
    dispatch_group_async(group, concurrentQueue, ^{
        NSLog(@"2");
    });
    //限制性
    //设置DISPATCH_TIME_FOREVER会一直等到前面任务都完成    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"can continue---------");

}