一、背景简介
平时在进行多线程处理任务时,有时候希望多个任务之间存在着一种联系,希望在所有的任务执行完后做一些总结性处理。
那么就可以将多个任务放在一个任务组中进行统一管理。dispatch提供了相应的API供我们完成这一需求。
二、dispatch_group_t相关属性介绍
1.dispatch_group_async(group, queue, block);
将block任务添加到queue队列,并被group组管理
2.dispatch_group_enter(group);
声明dispatch_group_enter(group)下面的任务由group组管理,group组的任务数+1
3.dispatch_group_leave(group);
相应的任务执行完成,group组的任务数-1
4.dispatch_group_create();
创建一个group组
5.dispatch_group_wait(group1, DISPATCH_TIME_FOREVER);
当前线程暂停,等待dispatch_group_wait(group1, DISPATCH_TIME_FOREVER)上面的任务执行完成后,线程才继续执行。
6.dispatch_group_notify(group1, queue1,block);
监听group组中任务的完成状态,当所有的任务都执行完成后,触发block块,执行总结性处理。
三、常见用法的区别
在使用group组处理任务时,常见的有两种组合。
其一:
dispatch_group_async(group, queue, block);
dispatch_group_notify(group1, queue1, block);
在这种组合下,根据任务是同步、异步又分为两种,这两种组合的执行代码与运行结果如下:
第一种:同步任务时
dispatch_queue_t queue1 = dispatch_queue_create("dispatchGroupMethod1.queue1", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group1 = dispatch_group_create(); dispatch_group_async(group1, queue1, ^{ dispatch_sync(queue1, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-同步任务执行-:%ld",@"任务1",(long)i); } }); }); dispatch_group_async(group1, queue1, ^{ dispatch_sync(queue1, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-同步任务执行-:%ld",@"任务2",(long)i); } }); }); // //等待上面的任务全部完成后,会往下继续执行 (会阻塞当前线程) // dispatch_group_wait(group1, DISPATCH_TIME_FOREVER); //等待上面的任务全部完成后,会收到通知执行block中的代码 (不会阻塞线程) dispatch_group_notify(group1, queue1, ^{ NSLog(@"Method1-全部任务执行完成"); });
同步任务运行结果:
2017-04-22 14:28:05.883 MyTestWorkProduct[27793:158785] 任务1-同步任务执行-:0 2017-04-22 14:28:05.884 MyTestWorkProduct[27793:159210] 任务1-同步任务执行-:0 2017-04-22 14:28:06.885 MyTestWorkProduct[27793:159210] 任务1-同步任务执行-:1 2017-04-22 14:28:06.885 MyTestWorkProduct[27793:158785] 任务1-同步任务执行-:1 2017-04-22 14:28:07.886 MyTestWorkProduct[27793:158785] 任务1-同步任务执行-:2 2017-04-22 14:28:07.886 MyTestWorkProduct[27793:159210] 任务1-同步任务执行-:2 2017-04-22 14:28:07.886 MyTestWorkProduct[27793:159186] Method1-全部任务执行完成
第二种:异步任务时
dispatch_queue_t queue1 = dispatch_queue_create("dispatchGroupMethod1.queue1", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group1 = dispatch_group_create(); dispatch_group_async(group1, queue1, ^{ dispatch_async(queue1, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-异步任务执行-:%ld",@"任务1",(long)i); } }); }); dispatch_group_async(group1, queue1, ^{ dispatch_async(queue1, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-异步任务执行-:%ld",@"任务2",(long)i); } }); }); // //等待上面的任务全部完成后,会往下继续执行 (会阻塞当前线程) // dispatch_group_wait(group1, DISPATCH_TIME_FOREVER); //等待上面的任务全部完成后,会收到通知执行block中的代码 (不会阻塞线程) dispatch_group_notify(group1, queue1, ^{ NSLog(@"Method1-全部任务执行完成"); });
异步任务运行结果:
2017-04-22 14:12:28.889 MyTestWorkProduct[27424:147249] Method1-全部任务执行完成 2017-04-22 14:12:29.893 MyTestWorkProduct[27424:147231] 任务2-异步任务执行-:0 2017-04-22 14:12:29.893 MyTestWorkProduct[27424:146850] 任务1-异步任务执行-:0 2017-04-22 14:12:30.896 MyTestWorkProduct[27424:147231] 任务2-异步任务执行-:1 2017-04-22 14:12:30.896 MyTestWorkProduct[27424:146850] 任务1-异步任务执行-:1 2017-04-22 14:12:31.901 MyTestWorkProduct[27424:147231] 任务2-异步任务执行-:2 2017-04-22 14:12:31.901 MyTestWorkProduct[27424:146850] 任务1-异步任务执行-:2
结论:dispatch_group_async(group, queue, block) 和 dispatch_group_notify(group1, queue1, block) 组合在执行同步任务时正常,在执行异步任务时不正常。
其二
dispatch_group_enter(group);
dispatch_group_leave(group);
dispatch_group_notify(group1, queue1,block);
在这种组合下,根据任务是同步、异步又分为两种,这两种组合的执行代码与运行结果如下:
第一种:同步任务时
dispatch_queue_t queue2 = dispatch_queue_create("dispatchGroupMethod2.queue2", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group2 = dispatch_group_create(); dispatch_group_enter(group2); dispatch_sync(queue2, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-同步任务执行-:%ld",@"任务1",(long)i); } dispatch_group_leave(group2); }); dispatch_group_enter(group2); dispatch_sync(queue2, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-同步任务执行-:%ld",@"任务2",(long)i); } dispatch_group_leave(group2); }); // //等待上面的任务全部完成后,会往下继续执行 (会阻塞当前线程) // dispatch_group_wait(group2, DISPATCH_TIME_FOREVER); //等待上面的任务全部完成后,会收到通知执行block中的代码 (不会阻塞线程) dispatch_group_notify(group2, queue2, ^{ NSLog(@"Method2-全部任务执行完成"); });
同步任务执行结果:
2017-04-22 14:28:05.884 MyTestWorkProduct[27793:159186] 任务2-同步任务执行-:0 2017-04-22 14:28:06.885 MyTestWorkProduct[27793:159186] 任务2-同步任务执行-:1 2017-04-22 14:28:07.886 MyTestWorkProduct[27793:159186] 任务2-同步任务执行-:2 2017-04-22 14:28:08.887 MyTestWorkProduct[27793:158785] 任务2-同步任务执行-:0 2017-04-22 14:28:09.888 MyTestWorkProduct[27793:158785] 任务2-同步任务执行-:1 2017-04-22 14:28:10.889 MyTestWorkProduct[27793:158785] 任务2-同步任务执行-:2 2017-04-22 14:28:10.889 MyTestWorkProduct[27793:159830] Method2-全部任务执行完成
第二种:异步任务时
dispatch_queue_t queue2 = dispatch_queue_create("dispatchGroupMethod2.queue2", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group2 = dispatch_group_create(); dispatch_group_enter(group2); dispatch_async(queue2, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-异步任务执行-:%ld",@"任务1",(long)i); } dispatch_group_leave(group2); }); dispatch_group_enter(group2); dispatch_async(queue2, ^{ for (NSInteger i =0; i<3; i++) { sleep(1); NSLog(@"%@-异步任务执行-:%ld",@"任务2",(long)i); } dispatch_group_leave(group2); }); // //等待上面的任务全部完成后,会往下继续执行 (会阻塞当前线程) // dispatch_group_wait(group2, DISPATCH_TIME_FOREVER); //等待上面的任务全部完成后,会收到通知执行block中的代码 (不会阻塞线程) dispatch_group_notify(group2, queue2, ^{ NSLog(@"Method2-全部任务执行完成"); });
异步任务执行结果:
2017-04-22 14:16:38.705 MyTestWorkProduct[27518:149631] 任务1-异步任务执行-:0 2017-04-22 14:16:38.705 MyTestWorkProduct[27518:149624] 任务2-异步任务执行-:0 2017-04-22 14:16:39.709 MyTestWorkProduct[27518:149631] 任务1-异步任务执行-:1 2017-04-22 14:16:39.709 MyTestWorkProduct[27518:149624] 任务2-异步任务执行-:1 2017-04-22 14:16:40.712 MyTestWorkProduct[27518:149624] 任务2-异步任务执行-:2 2017-04-22 14:16:40.712 MyTestWorkProduct[27518:149631] 任务1-异步任务执行-:2 2017-04-22 14:16:40.713 MyTestWorkProduct[27518:149631] Method2-全部任务执行完成
结论:
dispatch_group_enter(group)、dispatch_group_leave(group) 和 dispatch_group_notify(group1, queue1,block) 组合在执行同步任务时正常,在执行异步任务时正常。