假如你說:像這樣的 GCD 多工應用的場景不太算多, 我說:但這不是你沒必要知道怎麼去處理使用GCD處理多工的事情的理由
其實在 iOS 開發中,像這樣的多工處理,很簡單,因為 Apple 已經幫你封裝好了各種好用的 API,比如 GCD,現在我就說下具體的用法,所有的註釋都在程式碼裡,寫的應該說是很詳細了。
dispatch_group:建立任務組,然後非同步執行加入到 group 的每個任務,比如向 group 新增了3個任務,那麼這3個任務,會同時執行的,由於每個任務執行時間(耗時)不一樣,所有在所有的任務都執行結束後,會呼叫 dispatch_group_notify,可以在這裡處理多個任務的結果。
dispatch_group_t group = dispatch_group_create(); // 建立任務組 dispatch_group_enter(group):// 建立任務,新增至 group dispatch_group_leave(group):// 任務結束,離開 group
// eg:
dispatch_group_enter(group);
// 建立任務(程式碼)
...
dispatch_group_leave(group);
複製程式碼
需要提醒的一點:使用dispatch_group建立的多工,enter 和 leave 必須成對出現,否則,就呵呵了~
- (void)testGroupMultitask
{
NSLog(@"testGroupMultitask===============");
// 1.建立任務組
dispatch_group_t group = dispatch_group_create();
// 2.加入第一個任務
dispatch_group_enter(group);
NSMutableString *groupResult = [NSMutableString string];
// 模擬一個6秒的請求
[self fakeRequestWithDelay:6 result:^(NSString *string, NSError *error) {
/*
在這裡我們設定的dispatch_group_wait時間是5秒,但是我們這個任務的回撥時間是6秒。所以結果是5秒過後wait超時,程式繼續往下執行,列印-> "wait時間已經到了"。
然而這個任務還線上程裡執行,一直到執行dispatch_group_leave這個任務才完成。
*/
NSString *result = [NSString stringWithFormat:@"任務組1完成 %@",string];
[groupResult appendString:result];
[groupResult appendString:@"\n"];
NSLog(@"------%@",string);
dispatch_group_leave(group);
}];
// 3.加入第二個任務
dispatch_group_enter(group);
/*
這裡我發現一個問題,我設定的dispatch_after的延時時間是3秒,也就是3秒後把block中的任務加入執行緒;
所以結果應該是在dispatch_group_wait時間內就能完成的,列印順序應該是在 "wait時間已經到了" 之前才對, 但是列印的順序卻是先列印:"wait時間已經到了",然後列印:任務組2完成;
我猜測這個延時執行的程式碼,是非同步的等待,並不是阻塞執行緒的,
*/
dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
dispatch_after(tt, dispatch_get_main_queue(), ^{
NSString *result = @"任務組2完成 delay 3 seconds";
[groupResult appendString:result];
[groupResult appendString:@"\n"];
NSLog(@"------%@",result);
dispatch_group_leave(group);
});
// 4.加入第三個任務
dispatch_group_enter(group);
NSString *result = @"任務組3完成";
[groupResult appendString:result];
[groupResult appendString:@"\n"];
NSLog(@"------%@",result);
dispatch_group_leave(group);
// 5.執行到這句程式碼後會等待5秒,等待關聯的任務組group裡的所有任務完成。如果在5秒內都完成了,返回0並繼續執行;如果超時未完成,返回非0並繼續執行。所以任務組裡的任務無論是否全部完成,都會繼續執行。
int waitTime = 5;
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime*NSEC_PER_SEC)));
NSLog(@"wait時間已經到了 %i seconds",waitTime);
// 6.notify會簡體關聯的任務組group中的所有任務是否都已完成(dispatch_group_enter和dispatch_group_leave匹配),完成了就會執行block
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"------所有任務組都完成了 \n %@",groupResult);
});
}
複製程式碼
執行以上程式碼,在控制檯輸出結果:
2016-07-10 17:53:10.397 | testGroupMultitask===============
2016-07-10 17:53:10.397 | ------任務組3完成
2016-07-10 17:53:15.399 | wait時間已經到了 5 seconds
2016-07-10 17:53:15.403 | ------任務組2完成 delay 3 seconds
2016-07-10 17:53:16.986 | ------delay 6 seconds
2016-07-10 17:53:16.987 |
------所有任務組都完成了
任務組3完成
任務組2完成 delay 3 seconds
任務組1完成 delay 6 seconds
複製程式碼
對照列印的結果,可以看出,上面group各任務的執行順序。
最後再說下,enter和leave,不成對的後果:就是這個缺少leave的任務,在開闢的子執行緒裡一直在等待結束,所以 dispatch_group_notify 一直收不到所有任務完成的通知