group,我所知道的用法,目前有一下两种:
dispatch_group_async(group, queue, ^(){});
我们知道,无论是同步或异步的任务,都需要加到队列中来执行,无论是串行还是并发.
如果是一系列的任务加入到串行队列中,那么很简单,所有的任务都是依次执行的,这样我们很好控制,只需要把需要执行的任务追加到这一系列任务的最后,那么等前面的任务都执行完后,就会执行我们最后追加的任务.
但是如果一系列的异步任务,加入到了一个串行队列里,这些任务都是并行执行,这些任务执行时间长短不一,我们很难去监听这么多个任务的完成情况,这时候,我们该怎么办?
可以使用dispatch_group
,顾名思义这是一个组…..
下面我们看一段代码:
void testGroup()
{
//创建一个group,这里虽然用了create,但是GCD兼容ARC和MRC
//所以我们这里不需要dispatch_release()
dispatch_group_t group = dispatch_group_create();
//这里我们获取一个全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//第一个参数是上面创建的组,第二个参数是异步任务要加入的队列,第三个参数就是block,代码块,要执行的代码.
dispatch_group_async(group, queue, ^(){NSLog(@"block01");});
dispatch_group_async(group, queue, ^(){NSLog(@"block02");});
dispatch_group_async(group, queue, ^(){NSLog(@"block03");});
/**
dispatch_group_notify
@discussion 意思是,监听第一个参数group,如果该group里面的任务全部都完成后,就会调用该方法,在queue中,执行block.
@param group 要监听的组
@param queue 当组结束时,将会把block里的任务提交到该queue中执行,这个参数不能为空.
@return void
*/
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"block done");
});
}
/*
输出:
2016-12-29 09:21:23.919 GCD-Group[29814:1253348] block02
2016-12-29 09:21:23.919 GCD-Group[29814:1253493] block01
2016-12-29 09:21:23.919 GCD-Group[29814:1253406] block03
2016-12-29 09:21:23.920 GCD-Group[29814:1253186] block done
*/
你执行时上面的代码时,有可能输出的结果是block01,block02,block03,block done这样的顺序,不过没关系,多运行几下,总会出现顺序颠倒的情况.
想要说的就是block done
一定会在上面那三个任务完成之后再进行执行.
因为block01,block02,block03
都加入到了group
当中,所以只有当group中的所有的任务都执行完毕后,才会去执行dispatch_group_notify
后面的代码.
dispatch_group_enter(group);
上面那种用法是书上提到的,那么下面我们看dispatch_group_enter(group)
这种用法,这种用法看起来更简单,不过不如上面那种更直观.
因为采用dispatch_group_enter(group)
这样的写法,需要在不同的地方,加入到组,并且标记好在什么地方离开组.话不多说,我们看一个实例:
有个场景,比如说,一个界面有两个接口,只有当两个接口都返回数据后,我们才去加载该界面.那么我们该如何去监听者两个网络请求都回来了呢?
难点在于,两个网络请求都是异步的,我们也不清楚它到底什么时候请求成功.我们可以看下如何使用dispatch_group_enter(group)
来解决这种问题.
- (void)viewDidLoad {
[super viewDidLoad];
//创建组对象,虽然有用到create,但是不用手动release.
_group = dispatch_group_create();
//声明下面的第一个方法要加入到组当中.
dispatch_group_enter(_group);
//该方法所执行的线程根据上下文来决定的.
[self requestNews:^(id posts) {
// code
}];
//同上
dispatch_group_enter(_group);
[self requestWethear:^(id posts) {
// code
}];
//group里面的所有任务完成后的回调.
//这个回调对于代码的位置没有固定的要求,放在_group创建的下面也行.
dispatch_group_notify(_group, dispatch_get_main_queue(), ^{
NSLog(@"group notify");
});
}
- (void)requestNews:(void(^)(id posts))success
{
NSLog(@"requestNews: %@", [NSThread currentThread]);
success(@{});
//下面的方法表示任务完成,离开组,如果没有调用,那么将会一直等待该任务的离开
//如果你没有调用下面的方法,也没有设置dispatch_group_wait
//那么你的dispatch_group_notify方法里面的block将永远都不会执行.
//如果该方法没有加入到组里面,但是调用了下面这个方法,那么程序将会崩溃.
dispatch_group_leave(_group);
}
- (void)requestWethear:(void(^)(id posts))success
{
success(@{});
//离开组
dispatch_group_leave(_group);
}
嗯..就酱.