场景
假设有这样一个场景:有3个任务A,B,C,任务B需要在任务A和任务C执行完毕之后才执行,但是我们又想实现异步执行,怎么办呢?这种场景经常出现在异步加载图片的时候,有的时候需要下载多张图片,在多张图片下载完毕之后再执行其他操作。
这个时候就需要GCD中的任务组dispatch_group_t
了
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"任务A");
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务C");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"任务B");
});
在使用dispatch_group_create
创建一个任务组之后,就可以向其中中添加任务了,因为我们需要异步操作,所以说参数使用并行队列。
在最后,使用dispatch_group_notify
来表示执行完任务A和任务C之后执行任务B。
问题:发现在使用的过程中,在任务A,任务C里面并不能写网络请求,如果dispatch_group_async
里执行的是异步代码dispatch_group_notify
会直接触发而不会等待异步任务完成在执行,所以这时候就需要dispatch_group_enter
、dispatch_group_level
dispatch_group_enter、dispatch_group_level
和dispatch_async相比,当我们调用n次dispatch_group_enter后再调用n次dispatch_group_level时,dispatch_group_notify会收到同步信号;这个特点使得它非常适合处理异步任务的同步,当异步任务开始前调用dispatch_group_enter异步任务结束后调用dispatch_group_leve。
- (void)groupSync
{
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(@"任务完成");
});
}
注意:上面的这个例子,你可以在网络任务开始的时候调用dispatch_group_enter,而在网络任务结果回调的时候调用dispatch_group_leave,这个时候就可以达到预想的效果了。
总结
如果dispatch_group_async里执行的是异步代码dispatch_group_notify会直接触发而不会等待异步任务完成,而dispatch_group_enter、和dispatch_group_leave则不会有这个问题,它们只需要在任务开始前enter结束后leave即可达到线程同步的效果。
网友评论