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