一、背景簡介
平時在進行多線程處理任務時,有時候希望多個任務之間存在着一種聯系,希望在所有的任務執行完后做一些總結性處理。
那么就可以將多個任務放在一個任務組中進行統一管理。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) 組合在執行同步任務時正常,在執行異步任務時正常。