GCD
队列组:dispatch_group
有时候我们会有这样的需求:分别异步执行2个耗时任务,然后当2个耗时任务都执行完毕后再回到主线程执行任务。这时候我们可以用到 GCD
的队列组。
- 调用队列组的
dispatch_group_async
先把任务放到队列中,然后将队列放入队列组中。或者使用队列组的dispatch_group_enter
、dispatch_group_leave
组合 来实现dispatch_group_async
。 - 调用队列组的
dispatch_group_notify
回到指定线程执行任务。或者使用dispatch_group_wait
回到当前线程继续向下执行(会阻塞当前线程)。
dispatch_group_notify
监听
group
中任务的完成状态,当所有的任务都执行完成后,追加任务到group
中,并执行任务。
/**
* 队列组 dispatch_group_notify
*/
- (void)groupNotify {
// 打印当前线程
NSLog(@"currentThread-->%@",[NSThread currentThread]);
NSLog(@"group-->begin");
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, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
// 模拟耗时操作
[NSThread sleepForTimeInterval:2];
// 打印当前线程
NSLog(@"1-->%@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2-->%@",[NSThread currentThread]);
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步任务1、任务2都执行完毕后,回到主线程执行下边任务
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3-->%@",[NSThread currentThread]);
}
NSLog(@"group-->end");
});
}
输出结果
currentThread-->{number = 1, name = main}
group-->begin
1-->{number = 5, name = (null)}
2-->{number = 6, name = (null)}
2-->{number = 6, name = (null)}
1-->{number = 5, name = (null)}
3-->{number = 1, name = main}
3-->{number = 1, name = main}
group-->end
从dispatch_group_notify
相关代码运行输出结果可以看出:当所有任务都执行完成之后,才执行dispatch_group_notify block
中的任务。
dispatch_group_wait
暂停当前线程(阻塞当前线程),等待指定的
group
中的任务执行完成后,才会往下继续执行。
/**
* 队列组 dispatch_group_wait
*/
- (void)groupWait {
NSLog(@"currentThread-->%@",[NSThread currentThread]);
NSLog(@"group-->begin");
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, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1-->%@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2-->%@",[NSThread currentThread]);
}
});
// 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"group-->end");
}
输出结果
currentThread-->{number = 1, name = main}
group-->begin
2-->{number = 5, name = (null)}
1-->{number = 4, name = (null)}
2-->{number = 5, name = (null)}
1-->{number = 4, name = (null)}
group-->end
从dispatch_group_wait
相关代码运行输出结果可以看出:当所有任务执行完成之后,才执行 dispatch_group_wait
之后的操作。但是,使用dispatch_group_wait
会阻塞当前线程。
dispatch_group_enter
、dispatch_group_leave
-
dispatch_group_enter
标志着一个任务追加到group
,执行一次,相当于group
中未执行完毕任务数+1 -
dispatch_group_leave
标志着一个任务离开了group
,执行一次,相当于group
中未执行完毕任务数-1。 - 当
group
中未执行完毕任务数为0的时候,才会使dispatch_group_wait
解除阻塞,以及执行追加到dispatch_group_notify
中的任务。
/**
* 队列组 dispatch_group_enter、dispatch_group_leave
*/
- (void)groupEnterAndLeave {
NSLog(@"currentThread-->%@",[NSThread currentThread]);
NSLog(@"group-->begin");
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1-->%@",[NSThread currentThread]);
}
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2-->%@",[NSThread currentThread]);
}
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程.
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3-->%@",[NSThread currentThread]);
}
NSLog(@"group_notify-->end");
});
// 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"group---end");
}
输出
currentThread-->{number = 1, name = main}
group-->begin
1-->{number = 4, name = (null)}
2-->{number = 3, name = (null)}
2-->{number = 3, name = (null)}
1-->{number = 4, name = (null)}
group---end
3-->{number = 1, name = main}
3-->{number = 1, name = main}
group_notify-->end
从dispatch_group_enter
、dispatch_group_leave
相关代码运行结果中可以看出:当所有任务执行完成之后,才执行dispatch_group_notify
中的任务。这里的dispatch_group_enter
、dispatch_group_leave
组合,其实等同于dispatch_group_async