dispatch_group的关键函数如下:
- dispatch_group_t 队列组对象类
- dispatch_group_async 先把任务放到队列中,然后再讲队列放入队列组
- dispatch_group_notify 用于获取执行完毕回调
- dispatch_wait 回到当前线程继续执行后面的操作(会阻塞当前线程)
- dispatch_group_enter 用于标志一个任务追加到group,执行一次,相当于group中未执行完毕任务数+1
- dispatch_group_leave 用于标志一个任务离开了group,执行一次,相当于group中未执行完毕任务数-1
面试题
想必很多小伙伴面试时都被这样问过:有n个请求(耗时操作)分别异步执行,当这些请求全部执行完了回主线程刷新UI。
吐槽:对于这么个老掉牙的问题,总被问真的很心烦,正所谓千年不死的老妖怪,万年难改的面试题。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"请求1");
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"请求2");
});
…
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@“请求n");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"所有请求执行完毕,刷新UI");
});
思路:
- 创建dispatch_group_t 队列组
- 将n个耗时操作用dispatch_group_async 函数放入异步队列中
- 使用dispatch_group_notify 接收回调,并在主队列中刷新UI
dispatch_wait 使用
个人理解为一个计数器,需要配合dispatch_group_enter 和dispatch_group_leave 使用。
如果当前队列组内有未执行完成的任务,那么他就会一直阻塞着其对应的队列。
只有未执行完成的任务数变为0时,才会解除阻塞,并执行后面追加到该队列组的其他任务。
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(group);//任务数 +1
dispatch_async(queue, ^{
NSLog(@"任务1");
dispatch_group_leave(group);//任务数 -1
});
dispatch_group_enter(group);//任务数 +1
dispatch_async(queue, ^{
NSLog(@"任务2");
dispatch_group_leave(group);//任务数 -1
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"所有请求执行完毕,刷新UI");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//等待上面任务全部完成后,往下继续执行(阻塞当前线程)
dispatch_group_async(group, queue, ^{
NSLog(@"任务3");
});
任务1 和任务2 异步并行执行,且在他们执行完前阻塞当前queue队列。
任务1 和任务2 全部执行完毕后,dispatch_group_wait解除阻塞,开始执行任务3。
所有任务都执行完成后,dispatch_group_notify回调。
从此也可以看出:这里的dispatch_group_enter、dispatch_group_leave 是组合使用的,其作用同于dispatch_group_async。
如果本文对你有帮助记得点个喜欢哈
网友评论