多線程之GCD隊列組

GCD 隊列組:dispatch_group

有時候我們會有這樣的需求:分別異步執(zhí)行2個耗時任務(wù),然后當(dāng)2個耗時任務(wù)都執(zhí)行完畢后再回到主線程執(zhí)行任務(wù)。這時候我們可以用到 GCD的隊列組。

  • 調(diào)用隊列組的 dispatch_group_async 先把任務(wù)放到隊列中,然后將隊列放入隊列組中。或者使用隊列組的 dispatch_group_enter、dispatch_group_leave 組合 來實現(xiàn)dispatch_group_async。
  • 調(diào)用隊列組的 dispatch_group_notify 回到指定線程執(zhí)行任務(wù)?;蛘呤褂?dispatch_group_wait回到當(dāng)前線程繼續(xù)向下執(zhí)行(會阻塞當(dāng)前線程)。

dispatch_group_notify

監(jiān)聽 group中任務(wù)的完成狀態(tài),當(dāng)所有的任務(wù)都執(zhí)行完成后,追加任務(wù)到 group中,并執(zhí)行任務(wù)。

/**
 * 隊列組 dispatch_group_notify
 */
- (void)groupNotify {
    
    // 打印當(dāng)前線程
    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, ^{
        // 追加任務(wù)1
        for (int i = 0; i < 2; ++i) {
            // 模擬耗時操作
            [NSThread sleepForTimeInterval:2];
            // 打印當(dāng)前線程
            NSLog(@"1-->%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        // 追加任務(wù)2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2-->%@",[NSThread currentThread]);
        }
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的異步任務(wù)1、任務(wù)2都執(zhí)行完畢后,回到主線程執(zhí)行下邊任務(wù)
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3-->%@",[NSThread currentThread]);
        }
        NSLog(@"group-->end");
    });
}

輸出結(jié)果

currentThread--><NSThread: 0x2818cae80>{number = 1, name = main}
group-->begin
1--><NSThread: 0x281844340>{number = 5, name = (null)}
2--><NSThread: 0x281840740>{number = 6, name = (null)}
2--><NSThread: 0x281840740>{number = 6, name = (null)}
1--><NSThread: 0x281844340>{number = 5, name = (null)}
3--><NSThread: 0x2818cae80>{number = 1, name = main}
3--><NSThread: 0x2818cae80>{number = 1, name = main}
group-->end

dispatch_group_notify相關(guān)代碼運行輸出結(jié)果可以看出:當(dāng)所有任務(wù)都執(zhí)行完成之后,才執(zhí)行dispatch_group_notify block中的任務(wù)。

dispatch_group_wait

暫停當(dāng)前線程(阻塞當(dāng)前線程),等待指定的 group中的任務(wù)執(zhí)行完成后,才會往下繼續(xù)執(zhí)行。

/**
 * 隊列組 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, ^{
        // 追加任務(wù)1
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1-->%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        // 追加任務(wù)2
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2-->%@",[NSThread currentThread]);
        }
    });
    // 等待上面的任務(wù)全部完成后,會往下繼續(xù)執(zhí)行(會阻塞當(dāng)前線程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"group-->end");
}

輸出結(jié)果

currentThread--><NSThread: 0x281246e40>{number = 1, name = main}
group-->begin
2--><NSThread: 0x2812cde00>{number = 5, name = (null)}
1--><NSThread: 0x2812c8640>{number = 4, name = (null)}
2--><NSThread: 0x2812cde00>{number = 5, name = (null)}
1--><NSThread: 0x2812c8640>{number = 4, name = (null)}
group-->end

dispatch_group_wait相關(guān)代碼運行輸出結(jié)果可以看出:當(dāng)所有任務(wù)執(zhí)行完成之后,才執(zhí)行 dispatch_group_wait之后的操作。但是,使用dispatch_group_wait 會阻塞當(dāng)前線程。

dispatch_group_enter、dispatch_group_leave

  • dispatch_group_enter標(biāo)志著一個任務(wù)追加到 group,執(zhí)行一次,相當(dāng)于group 中未執(zhí)行完畢任務(wù)數(shù)+1
  • dispatch_group_leave標(biāo)志著一個任務(wù)離開了 group,執(zhí)行一次,相當(dāng)于group 中未執(zhí)行完畢任務(wù)數(shù)-1。
  • 當(dāng) group中未執(zhí)行完畢任務(wù)數(shù)為0的時候,才會使dispatch_group_wait解除阻塞,以及執(zhí)行追加到dispatch_group_notify中的任務(wù)。
/**
 * 隊列組 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, ^{
        // 追加任務(wù)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, ^{
        // 追加任務(wù)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(), ^{
        // 等前面的異步操作都執(zhí)行完畢后,回到主線程.
        for (int i = 0; i < 2; ++i) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3-->%@",[NSThread currentThread]);
        }
        NSLog(@"group_notify-->end");
    });
    // 等待上面的任務(wù)全部完成后,會往下繼續(xù)執(zhí)行(會阻塞當(dāng)前線程)
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"group---end");
}

輸出

currentThread--><NSThread: 0x282901a80>{number = 1, name = main}
group-->begin
1--><NSThread: 0x28294b7c0>{number = 4, name = (null)}
2--><NSThread: 0x282948cc0>{number = 3, name = (null)}
2--><NSThread: 0x282948cc0>{number = 3, name = (null)}
1--><NSThread: 0x28294b7c0>{number = 4, name = (null)}
group---end
3--><NSThread: 0x282901a80>{number = 1, name = main}
3--><NSThread: 0x282901a80>{number = 1, name = main}
group_notify-->end

dispatch_group_enter、dispatch_group_leave相關(guān)代碼運行結(jié)果中可以看出:當(dāng)所有任務(wù)執(zhí)行完成之后,才執(zhí)行dispatch_group_notify 中的任務(wù)。這里的dispatch_group_enter、dispatch_group_leave組合,其實等同于dispatch_group_async

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容