1.隊列組的基本概念
1.隊列組(dispatch_group_t):用來管理隊列中任務的執(zhí)行列吼。
2.隊列組的使用步驟:
- 1.創(chuàng)建隊列組
- 2.創(chuàng)建隊列
- 3.使用隊列組異步函數(shù)(dispatch_group_async)封裝任務,把任務提交到隊列中
- 4.監(jiān)聽任務的完成情況(dispatch_group_notify)
2.隊列組的基本使用
放入隊列組的隊列可以是多個隊列宏邮,可以是串行隊列或者并發(fā)隊列。
加入同一個串行隊列撕贞,則加入的任務會在同一個子線程按順序執(zhí)行,隊列組的監(jiān)聽沒有實際意義,直接把任務加到這個串行隊列即可靡挥。
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務1——準備休眠2秒,%@",[NSThread currentThread]);
sleep(2);
NSLog(@"任務1——完成");
});
dispatch_group_async(group, queue, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
NSLog(@"主線程結(jié)束");
打印結(jié)果:
2020-02-28 11:37:23.446839+0800 Test[20493:1346501] 主線程結(jié)束
2020-02-28 11:37:23.446901+0800 Test[20493:1346542] 任務1——準備休眠2秒,<NSThread: 0x6000037ea500>{number = 3, name = (null)}
2020-02-28 11:37:25.451652+0800 Test[20493:1346542] 任務1——完成
2020-02-28 11:37:25.451959+0800 Test[20493:1346542] 任務2——準備休眠1秒,<NSThread: 0x6000037ea500>{number = 3, name = (null)}
2020-02-28 11:37:26.455702+0800 Test[20493:1346542] 任務2——完成
2020-02-28 11:37:26.456015+0800 Test[20493:1346501] 任務組中的任務完成
把任務加入不同的串行隊列,則加入的任務會在兩個子線程并發(fā)執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue1 = dispatch_queue_create("queue_test1", DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務1——準備休眠2秒,%@",[NSThread currentThread]);
sleep(2);
NSLog(@"任務1——完成");
});
dispatch_group_async(group, queue1, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
NSLog(@"主線程結(jié)束");
打印結(jié)果:
2020-02-28 11:39:30.363815+0800 Test[20533:1349943] 主線程結(jié)束
2020-02-28 11:39:30.363881+0800 Test[20533:1349995] 任務2——準備休眠1秒,<NSThread: 0x600001c1b180>{number = 4, name = (null)}
2020-02-28 11:39:30.363901+0800 Test[20533:1349994] 任務1——準備休眠2秒,<NSThread: 0x600001c1ccc0>{number = 3, name = (null)}
2020-02-28 11:39:31.367371+0800 Test[20533:1349995] 任務2——完成
2020-02-28 11:39:32.369266+0800 Test[20533:1349994] 任務1——完成
2020-02-28 11:39:32.369610+0800 Test[20533:1349943] 任務組中的任務完成
把任務加入同一個并發(fā)隊列鸯绿,會在不同線程并發(fā)執(zhí)行跋破。
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務1——準備休眠2秒,%@",[NSThread currentThread]);
sleep(2);
NSLog(@"任務1——完成");
});
dispatch_group_async(group, queue, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
NSLog(@"主線程結(jié)束");
打印結(jié)果:
2020-02-28 14:16:27.847481+0800 Test[21744:1447421] 主線程結(jié)束
2020-02-28 14:16:27.847552+0800 Test[21744:1447471] 任務2——準備休眠1秒,<NSThread: 0x60000265d500>{number = 4, name = (null)}
2020-02-28 14:16:27.847570+0800 Test[21744:1447472] 任務1——準備休眠2秒,<NSThread: 0x6000026560c0>{number = 3, name = (null)}
2020-02-28 14:16:28.848630+0800 Test[21744:1447471] 任務2——完成
2020-02-28 14:16:29.851477+0800 Test[21744:1447472] 任務1——完成
2020-02-28 14:16:29.851826+0800 Test[21744:1447421] 任務組中的任務完成
把任務放入不同的并發(fā)隊列,會在不同線程并發(fā)執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue1 = dispatch_queue_create("queue_test1", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務1——準備休眠2秒,%@",[NSThread currentThread]);
sleep(2);
NSLog(@"任務1——完成");
});
dispatch_group_async(group, queue1, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
NSLog(@"主線程結(jié)束");
打印結(jié)果:
2020-02-28 14:17:43.878824+0800 Test[21779:1449847] 主線程結(jié)束
2020-02-28 14:17:43.878918+0800 Test[21779:1449944] 任務1——準備休眠2秒,<NSThread: 0x600003e6d900>{number = 3, name = (null)}
2020-02-28 14:17:43.878918+0800 Test[21779:1449949] 任務2——準備休眠1秒,<NSThread: 0x600003e61480>{number = 4, name = (null)}
2020-02-28 14:17:44.881581+0800 Test[21779:1449949] 任務2——完成
2020-02-28 14:17:45.882695+0800 Test[21779:1449944] 任務1——完成
2020-02-28 14:17:45.883016+0800 Test[21779:1449847] 任務組中的任務完成
總結(jié):加入隊列組的任務可以是串行隊列的瓶蝴,也可以是并發(fā)隊列的毒返。可以是同一個隊列的任務舷手,也可以是多個隊列的任務拧簸。但是如果是加入同一個串行隊列,本來就會按順序在同一個線程執(zhí)行男窟。
核心方法
- 1.dispatch_group_create() 創(chuàng)建隊列組
- 2.dispatch_group_async(group, queue, ^{}); 往隊列組添加任務
- 3.dispatch_group_notify(group, dispatch_get_main_queue(), ^{}); //讓隊列組監(jiān)聽任務的完成,把監(jiān)聽任務放在添加任務前不一定有效(實驗在監(jiān)聽之后添加一萬個任務,dispatch_group_notify中的方法在中間調(diào)用)盆赤,所以dispatch_group_notify必須寫在添加完所有任務之后。
3.隊列組的dispatch_group_enter,dispatch_group_leave函數(shù)對用法
隊列組的函數(shù)對用法是目前比較少見的用法, 這個用法比較老, 好處是嚴格的控制/監(jiān)聽了每個進入隊列組的任務
使用步驟:
- 1.創(chuàng)建隊列組
- 2.創(chuàng)建隊列歉眷,使用異步函數(shù),如果使用同步函數(shù)牺六,添加的方法會按順序執(zhí)行,沒有實際意義姥芥。
- 3.開啟隊列組兔乞,通過函數(shù)添加任務
注意點:在通過函數(shù)添加任務之前必須調(diào)用dispatch_group_enter(group);,用來確定往group這個隊列組添加任務凉唐,任務代碼結(jié)束后必須調(diào)用dispatch_group_leave(group);用來確保已經(jīng)離開隊列組庸追,否則不會調(diào)用dispatch_group_notify這個監(jiān)聽方法。
dispatch_queue_t queue = dispatch_queue_create("queue test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務1——準備休眠2秒,%@",[NSThread currentThread]);
sleep(2);
NSLog(@"任務1——完成");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
打印結(jié)果:
2020-02-28 14:44:05.307563+0800 Test[22253:1494879] 任務1——準備休眠2秒,<NSThread: 0x60000374a240>{number = 3, name = (null)}
2020-02-28 14:44:05.307735+0800 Test[22253:1494889] 任務2——準備休眠1秒,<NSThread: 0x600003744880>{number = 4, name = (null)}
2020-02-28 14:44:06.311042+0800 Test[22253:1494889] 任務2——完成
2020-02-28 14:44:07.311707+0800 Test[22253:1494879] 任務1——完成
2020-02-28 14:44:07.312074+0800 Test[22253:1494785] 任務組中的任務完成
對于加入隊列組中的隊列是串行還是并行台囱,同一個隊列還是多個隊列的結(jié)果淡溯,和基本用法中相同
4. dispatch_group_wait函數(shù)
dispatch_group_wait能阻塞線程,判斷隊列組的任務能否在規(guī)定時間內(nèi)完成簿训,若在規(guī)定時間內(nèi)完成會返回0咱娶,否則是非0值。然后在到達規(guī)定時間后不管隊列組內(nèi)任務是否完成强品,往下執(zhí)行代碼膘侮。
該函數(shù)和dispatch_group_notify函數(shù)不沖突。
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue1 = dispatch_queue_create("queue_test1", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任務1——準備休眠5秒,%@",[NSThread currentThread]);
sleep(5);
NSLog(@"任務1——完成");
});
dispatch_group_async(group, queue1, ^{
NSLog(@"任務2——準備休眠1秒,%@",[NSThread currentThread]);
sleep(1);
NSLog(@"任務2——完成");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任務組中的任務完成");
});
// 同步執(zhí)行的榛,等待隊列組time的時間后執(zhí)行后面的代碼琼了,如果隊列組中的任務都完成了,就返回0,如果沒完成雕薪,就返回非0值
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
// 等待tiemr秒的時間昧诱,不管隊列中任務是否完成,都繼續(xù)往下執(zhí)行所袁,如果該時間內(nèi)任務完成了就返回0盏档,否則是非零值
long n = dispatch_group_wait(group, timer);
NSLog(@"%ld", n);
NSLog(@"主線程結(jié)束");
打印結(jié)果
2020-02-28 15:03:56.876353+0800 Test[22672:1529852] 任務2——準備休眠1秒,<NSThread: 0x6000030f8300>{number = 4, name = (null)}
2020-02-28 15:03:56.876353+0800 Test[22672:1529851] 任務1——準備休眠5秒,<NSThread: 0x6000030fc380>{number = 3, name = (null)}
2020-02-28 15:03:57.876948+0800 Test[22672:1529852] 任務2——完成
2020-02-28 15:03:58.877405+0800 Test[22672:1529113] 49
2020-02-28 15:03:58.877693+0800 Test[22672:1529113] 主線程結(jié)束
2020-02-28 15:04:01.880121+0800 Test[22672:1529851] 任務1——完成
2020-02-28 15:04:01.880516+0800 Test[22672:1529113] 任務組中的任務完成
由上述結(jié)果可以知道:
在執(zhí)行過dispatch_group_wait函數(shù)后,主線程不再往下執(zhí)行燥爷,主線程等待2秒后繼續(xù)執(zhí)行代碼蜈亩,此時任務1并沒有完成,所以dispatch_group_wait函數(shù)可以阻斷線程一定時間前翎。
在任務1完成后勺拣,dispatch_group_notify繼續(xù)執(zhí)行里面的代碼,所以說明dispatch_group_notify和dispatch_group_wait不沖突鱼填。