1楼眷、什么是 GCD 十性?
GCD 是蘋果公司為多核的并行運算提出的解決方案限佩,它基于 C 語言葵诈,全稱 Grand Central Dispatch裸弦,有人叫它“牛逼的中心調(diào)度”。
2作喘、GCD 用途
通過 GCD理疙,開發(fā)者不用再直接跟線程打交道了,只需要向隊列中添加代碼塊即可泞坦,GCD 在后端管理著一個線程池窖贤。GCD 不僅決定著你的代碼塊將在哪個線程被執(zhí)行,它還根據(jù)可用的系統(tǒng)資源對這些線程進行管理贰锁。這樣可以將開發(fā)者從線程管理的工作中解放出來赃梧,通過集中的管理線程,來緩解大量線程被創(chuàng)建的問題豌熄。
GCD 帶來的另一個重要改變是授嘀,作為開發(fā)者可以將工作考慮為一個隊列,而不是一堆線程锣险,這種并行的抽象模型更容易掌握和使用蹄皱。
首先睬愤,系統(tǒng)提供給你一個叫做 主隊列(main queue) 的特殊隊列悬赏。和其它串行隊列一樣,這個隊列中的任務(wù)一次只能執(zhí)行一個慢味。然而纷妆,它能保證所有的任務(wù)都在主線程執(zhí)行盔几,而主線程是唯一可用于更新 UI 的線程晴弃。這個隊列就是用于發(fā)生消息給 UIView 或發(fā)送通知的掩幢。
系統(tǒng)同時提供給你好幾個并發(fā)隊列。它們叫做 全局調(diào)度隊列(Global Dispatch Queues) 上鞠。目前的四個全局隊列有著不同的優(yōu)先級:background际邻、low、default 以及 high芍阎。要知道世曾,Apple 的 API 也會使用這些隊列,所以你添加的任何任務(wù)都不會是這些隊列中唯一的任務(wù)谴咸。
最后轮听,你也可以創(chuàng)建自己的串行隊列或并發(fā)隊列。這就是說岭佳,至少有五個隊列任你處置:主隊列血巍、四個全局調(diào)度隊列,再加上任何你自己創(chuàng)建的隊列珊随。
3述寡、GCD 術(shù)語
- 串行(Serial):讓任務(wù)一個接著一個地執(zhí)行(one by one)
- 并發(fā)(Concurrent):可以讓多個任務(wù)并發(fā)執(zhí)行(自動開啟多個線程柿隙,同時執(zhí)行任務(wù)),并發(fā)只有在異步(dispatch_async)函數(shù)下才有效
- 同步(Synchronous):在當(dāng)前線程中執(zhí)行任務(wù)鲫凶,不具備開啟新線程的能力
- 異步(Asynchronous):在新的線程中執(zhí)行任務(wù)禀崖,具備開啟新線程的能力
4、GCD 優(yōu)點
- GCD 能通過推遲昂貴計算任務(wù)并在后臺運行它們來改善你的應(yīng)用的響應(yīng)性能螟炫。
- GCD 提供一個易于使用的并發(fā)模型而不僅僅只是鎖和線程波附,幫助我們避開并發(fā)陷阱。
- GCD 具有在常見模式(例如單例)上用更高性能的原語優(yōu)化你的代碼的潛在能力昼钻。
- GCD 會自動利用更多的CPU內(nèi)核(比如雙核叶雹、四核)
5、GCD 使用
- (1) 認識主隊列换吧,感受串行隊列的運行,運行結(jié)果打印的是 1折晦,2,3沾瓦,4满着,順序執(zhí)行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
NSLog(@"1");
});
dispatch_async(mainQueue, ^{
NSLog(@"2");
});
dispatch_async(mainQueue, ^{
NSLog(@"3");
});
dispatch_async(mainQueue, ^{
NSLog(@"4");
});
- (2) 認識全局隊列,體驗并發(fā)隊列的運行贯莺,運行結(jié)果隨機打臃缋:2,3缕探,1魂莫,4,隨機執(zhí)行
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
NSLog(@"1");
});
dispatch_async(defaultQueue, ^{
NSLog(@"2");
});
dispatch_async(defaultQueue, ^{
NSLog(@"3");
});
dispatch_async(defaultQueue, ^{
NSLog(@"4");
});
- (3) 創(chuàng)建自定義隊列
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"4");
dispatch_sync(concurrentQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"5");
});
NSLog(@"6");
});
- (4) GCD在單例中的運用 dispatch_once
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"onceToken");
});
- (5) 延遲加載 dispatch_after
double delayInSeconds = 2.0;
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, mainQueue, ^{
NSLog(@"延時執(zhí)行的2秒");
});
- (6) 調(diào)度組 dispatch_group_t
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, defaultQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"1");
});
dispatch_group_async(group, defaultQueue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2");
});
dispatch_group_notify(group, defaultQueue, ^{
NSLog(@"3");
});
// 等價于
// dispatch_group_enter(group);
// dispatch_async(defaultQueue, ^{
//
// NSLog(@"1");
// dispatch_group_leave(group);
// });
- (7) dispatch_barrier_async
在前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行爹耗,而且它后面的任務(wù)等它執(zhí)行完成之后才會執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("barrierExecute", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"3");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"4");
});
- (8) 執(zhí)行某個代碼 dispatch_apply
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(5, defaultQueue, ^(size_t i) {
NSLog(@"%lu",i);
});