dispatch_group_t 日常使用注意事項


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM