在實際的開發中,對於多線程的使用是多種多樣的,因爲需求的不同,處理邏輯也不同。
現在有兩個耗時操作A和B,現在需要A和B都異步執行,當A和B都執行完成後再執行C。
這樣的操作邏輯很常見,例如:一個界面需要展示兩個接口請求的數據,需要兩個接口全部請求完成才能刷新視圖,展示數據。
對於這樣的操作邏輯,對於這樣的操作要求,我們可以使用隊列組來完成。
隊列組的使用
隊列組的使用我分爲3種方式:
1、通知方式:dispatch_group_notify
2、等待方式(堵塞方式):dispatch_group_wait
3、進入走出方式:dispatch_group_enter、dispatch_group_leave
無論是哪一種方式,都需要先去創建隊列組、創建隊列和創建任務。
1、創建隊列組:
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//獲取全局並行隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
通知方式:dispatch_group_notify
- (void)queueGroupNotify{
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//獲取全局並行隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//創建異步任務
dispatch_group_async(group, queue, ^{
//任務1
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務1的執行=====%d", i);
}
});
//創建異步任務
dispatch_group_async(group, queue, ^{
//任務2
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務2的執行=====%d", i);
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//任務3
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"回到主線程執行=====%d", i);
}
});
}
打印結果:
2020-03-18 16:11:26.065895+0800 GCDdemo[87505:1358550] 任務2的執行=====0
2020-03-18 16:11:26.065937+0800 GCDdemo[87505:1358551] 任務1的執行=====0
2020-03-18 16:11:28.071042+0800 GCDdemo[87505:1358550] 任務2的執行=====1
2020-03-18 16:11:28.071042+0800 GCDdemo[87505:1358551] 任務1的執行=====1
2020-03-18 16:11:30.075650+0800 GCDdemo[87505:1358551] 任務1的執行=====2
2020-03-18 16:11:30.075663+0800 GCDdemo[87505:1358550] 任務2的執行=====2
2020-03-18 16:11:32.077253+0800 GCDdemo[87505:1358470] 回到主線程執行=====0
2020-03-18 16:11:34.078721+0800 GCDdemo[87505:1358470] 回到主線程執行=====1
2020-03-18 16:11:36.079946+0800 GCDdemo[87505:1358470] 回到主線程執行=====2
從上面的打印結果可以看出:任務1和任務2是異步執行的,並且在任務1和任務2執行完成後纔回到主線程執行。
等待方式(堵塞方式):dispatch_group_wait
- (void)queueGroupWait{
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//獲取全局並行隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//創建異步任務
dispatch_group_async(group, queue, ^{
//任務1
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務1的執行=====%d", i);
}
});
//創建異步任務
dispatch_group_async(group, queue, ^{
//任務2
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務2的執行=====%d", i);
}
});
/**
DISPATCH_TIME_NOW (0ull) 立即執行任務3,不等待
DISPATCH_TIME_FOREVER (~0ull) 等待上面兩個任務執行完成在執行任務3
*/
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
//任務3
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"回到主線程執行=====%d", i);
}
}
打印結果:
2020-03-18 16:21:22.095224+0800 GCDdemo[87837:1367632] 任務2的執行=====0
2020-03-18 16:21:22.095228+0800 GCDdemo[87837:1367630] 任務1的執行=====0
2020-03-18 16:21:24.099197+0800 GCDdemo[87837:1367632] 任務2的執行=====1
2020-03-18 16:21:24.099197+0800 GCDdemo[87837:1367630] 任務1的執行=====1
2020-03-18 16:21:26.101743+0800 GCDdemo[87837:1367630] 任務1的執行=====2
2020-03-18 16:21:26.101750+0800 GCDdemo[87837:1367632] 任務2的執行=====2
2020-03-18 16:21:28.103304+0800 GCDdemo[87837:1367440] 回到主線程執行=====0
2020-03-18 16:21:30.104813+0800 GCDdemo[87837:1367440] 回到主線程執行=====1
2020-03-18 16:21:32.106304+0800 GCDdemo[87837:1367440] 回到主線程執行=====2
從上面的打印結果可以看出:任務1和任務2是異步執行的,並且在任務1和任務2執行完成後纔回到主線程執行。
進入走出方式:dispatch_group_enter、dispatch_group_leave
注意:dispatch_group_enter和dispatch_group_leave必須成對出現,這個組合等同於dispatch_group_async
- (void)queueGroupEnterLeace{
//創建隊列組
dispatch_group_t group = dispatch_group_create();
//獲取全局並行隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//進組
dispatch_group_enter(group);
//創建異步任務,這裏不需要使用dispatch_group_async創建任務,使用dispatch_async
dispatch_async(queue, ^{
//任務1
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務1的執行=====%d", i);
}
//出組
dispatch_group_leave(group);
});
//進組
dispatch_group_enter(group);
dispatch_async(queue, ^{
//任務2
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"任務2的執行=====%d", i);
}
//出組
dispatch_group_leave(group);
});
//通知
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//任務3
for (int i = 0; i < 3; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"回到主線程執行=====%d", i);
}
});
}
打印結果:
2020-03-18 16:27:18.437480+0800 GCDdemo[88018:1373486] 任務2的執行=====0
2020-03-18 16:27:18.437479+0800 GCDdemo[88018:1373485] 任務1的執行=====0
2020-03-18 16:27:20.442395+0800 GCDdemo[88018:1373486] 任務2的執行=====1
2020-03-18 16:27:20.442395+0800 GCDdemo[88018:1373485] 任務1的執行=====1
2020-03-18 16:27:22.447306+0800 GCDdemo[88018:1373486] 任務2的執行=====2
2020-03-18 16:27:22.447331+0800 GCDdemo[88018:1373485] 任務1的執行=====2
2020-03-18 16:27:24.448925+0800 GCDdemo[88018:1373403] 回到主線程執行=====0
2020-03-18 16:27:26.450413+0800 GCDdemo[88018:1373403] 回到主線程執行=====1
2020-03-18 16:27:28.451925+0800 GCDdemo[88018:1373403] 回到主線程執行=====2
從上面的打印結果可以看出:任務1和任務2是異步執行的,並且在任務1和任務2執行完成後纔回到主線程執行。