GCD中提供了两个函数,可以实现此功能,分别是dispatch_barrier_(a)sync和dispatch_group_(a)sync。
简单写一下两种函数的使用方式。
1.dispatch_barrier_(a)sync
dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"111");
});
dispatch_sync(queue, ^{
NSLog(@“222”);
});
dispatch_barrier_async(queue, ^{
NSLog(@"barrier finished");
});
NSLog(@"main tread");
dispatch_async(queue, ^{
NSLog(@“333”);
});
dispatch_async(queue, ^{
NSLog(@“444”);
});
2017-12-20 14:07:11.774484+0800 GCD[33826:2126185] 111
2017-12-20 14:07:11.774517+0800 GCD[33826:2126192] 222
2017-12-20 14:07:11.774540+0800 GCD[33826:2126069] main thread
2017-12-20 14:07:11.774715+0800 GCD[33826:2126192] barrier finished
2017-12-20 14:07:11.774836+0800 GCD[33826:2126185] 333
2017-12-20 14:07:11.774837+0800 GCD[33826:2126192] 444
dispatch_barrier_async换成dispatch_barrier_sync之后log如下
2017-12-20 14:07:51.093250+0800 GCD[33878:2127341] 222
2017-12-20 14:07:51.093250+0800 GCD[33878:2127340] 111
2017-12-20 14:07:51.093466+0800 GCD[33878:2127248] barrier finished
2017-12-20 14:07:51.093604+0800 GCD[33878:2127248] main thread
2017-12-20 14:07:51.093742+0800 GCD[33878:2127341] 333
2017-12-20 14:07:51.093786+0800 GCD[33878:2127338] 444
dispatch_barrier_sync的作用是阻塞当前线程,把queue中的所有任务执行完毕之后,再去执行barrier的block
dispatch_barrier_async不阻塞当前线程,调用之后,立即返回当前线程,继续执行后面的代码。
总之,dispatch_barrier_(a)sync的执行顺序就是先执行barrier block之前的所有任务,然后执行barrier block中的任务,最后执行barrier block之后提交的任务。
2.dispatch_group
dispatch_queue_t queue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"group 1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"group 2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"group 3");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"group finished");
});
NSLog(@"666");
2017-12-20 14:18:53.984247+0800 GCD[34045:2139050] group 2
2017-12-20 14:18:53.984247+0800 GCD[34045:2139052] group 1
2017-12-20 14:18:53.984247+0800 GCD[34045:2139051] group 3
2017-12-20 14:18:53.984775+0800 GCD[34045:2138995] 666
2017-12-20 14:18:53.990947+0800 GCD[34045:2138995] group finished
与dispatch_barrier_(a)sync不同的是加入到group中的queue可以是不同的queue。
如果我们执行异步请求的时候如何保证在异步任务完成后,再去执行某段代码呢?这时候就要用到dispatch_group_enter和dispatch_group_leave了
dispatch_group_enter和dispatch_group_leave是成对出现的,出现数量必须保持一致。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];//发送一个网络请求
NSLog(@"1111");
dispatch_group_leave(group);
});
});
dispatch_group_async(group, queue, ^{
NSLog(@"group 2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"group 3");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"group finished");
});
NSLog(@"666");
2017-12-20 14:24:17.069952+0800 GCD[34215:2145287] group 2
2017-12-20 14:24:17.069952+0800 GCD[34215:2145285] group 3
2017-12-20 14:24:19.070292+0800 GCD[34215:2145288] 1111
2017-12-20 14:24:19.070640+0800 GCD[34215:2145119] 666
2017-12-20 14:24:19.076618+0800 GCD[34215:2145119] group finished
这样就可以用来处理多个异步任务,任务完成后统一处理任务逻辑了。