GCD(Grand Central Dispatch)
GCD是從iOS 4開始引入的新一代的多線程編程技術(shù)。
libdispatch是蘋果的一個庫 提供gcd使用
開發(fā)者只需定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中,GCD就能生成必要的線程并有計劃的執(zhí)行任務(wù)。并且由于線程管理是作為系統(tǒng)的一部分來實現(xiàn)的,因此系統(tǒng)可以統(tǒng)一管理,它會決定什么時候創(chuàng)建新線程,創(chuàng)建哪些新線程,多個任務(wù)是順序執(zhí)行還是并發(fā)執(zhí)行。這樣就比以前的線程編程更有效率
一 、 創(chuàng)建隊列
dispatch_queue_create 用于創(chuàng)建用戶線程隊列??梢詣?chuàng)建Serial/Concurrent Dispatch Queue 兩種隊列,即串行與并行隊列。
//part1 隊列標(biāo)示符 區(qū)分是那個隊列 一般寫反域名 如com.baidu.queue 不要加@
//part2 標(biāo)示當(dāng)前隊列類型 DISPATCH_QUEUE_SERIAL 標(biāo)示串行隊列 DISPATCH_QUEUE_CONCURRENT 并行隊列
dispatch_queue_t queue = dispatch_queue_create("com.baidu.queue", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建同步任務(wù)
//part1 同步加到哪個隊列當(dāng)中
//part2 block 寫要執(zhí)行的同步代碼
dispatch_sync(queue, ^{
[NSThread isMainThread]?NSLog(@"主線程0"):NSLog(@"分線程0");
});
//創(chuàng)建異步任務(wù)
dispatch_async(queue, ^{
[NSThread isMainThread]?NSLog(@"主線程1"):NSLog(@"分線程1");
});
dispatch_async(queue, ^{
[NSThread isMainThread]?NSLog(@"主線程2"):NSLog(@"分線程2");
});
dispatch_sync(queue, ^{
[NSThread isMainThread]?NSLog(@"主線程3"):NSLog(@"分線程3");
});
創(chuàng)建串行隊列
可以創(chuàng)建多個串行隊列,串行隊列也可以并行執(zhí)行。不能隨意的大量生產(chǎn)Serial Dispatch Queue。每創(chuàng)建一個串行隊列,系統(tǒng)就會對應(yīng)創(chuàng)建一個線程,同時這些線程都是并行執(zhí)行的,只是在串行隊列中的任務(wù)是串行執(zhí)行的。大量的創(chuàng)建串行隊列會導(dǎo)致大量消耗內(nèi)存,這是不可取的做法
創(chuàng)建并行隊列
并發(fā)隊列創(chuàng)建多少都沒有問題,因為Concurrent Dispatch Queue所使用的線程由系統(tǒng)的XNU內(nèi)核高效管理,不會影響系統(tǒng)性能。
二、Main&Global Dispatch Queue
系統(tǒng)為我們提供了兩種調(diào)度隊列 這兩種隊列不需要我們創(chuàng)建 只是在我們使用時獲取一下
Main Dispatch Queue是在主線程中執(zhí)行任務(wù)的Dispatch Queue。因為主線程只有一個,所以Main Dispatch Queue是Serial Dispatch Queue。追加到Main Dispatch Queue中的任務(wù)將在主線程中執(zhí)行。因為是在主線程中執(zhí)行,所以應(yīng)該只將用戶界面更新等一些必須在主線程中執(zhí)行的任務(wù)追加到Main Dispatch Queue中。
獲取Main Dispatch Queue的代碼如下:
dispatch_queue_t queue = dispatch_get_main_queue();
Global Dispatch Queue是全局都能使用的Concurrent Dispatch Queue。大多數(shù)情況下,可以不必通過dispatch_queue_create函數(shù)生成Concurrent Dispatch Queue,而是只需要獲取Global Dispatch Queue使用即可。Global Dispatch Queue有四個優(yōu)先級,分別是high、default、low、background。
獲取Global Dispatch Queue的代碼如下:
//獲得系統(tǒng)提供的并行隊列g(shù)lobal
//part1 設(shè)置當(dāng)前隊列的優(yōu)先級 DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn)級別
//part2 預(yù)留符號 一般填寫 0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
三、dispatch_async 和dispatch_sync
dispatch_sync(),同步添加操作。它是等待添加進(jìn)隊列里面的操作完成之后再繼續(xù)執(zhí)行。
dispatch_async ,異步添加進(jìn)任務(wù)隊列,它不會做任何等待
//開啟異步任務(wù)
dispatch_async(queue, ^{
//主線程隊列
//回到main隊列時 不要使用dispatch_sync 因為這樣會造成線程死鎖
dispatch_async(dispatch_get_main_queue(), ^{
//刷新界面操作
});
});
同步提交任務(wù)需注意:調(diào)用此函數(shù)的隊列和同步提交任務(wù)的目標(biāo)隊列都是當(dāng)前隊列話 會造成死鎖
四、dispatch_once 實現(xiàn)單例中的線程同步
使用dispatch_once函數(shù)
該函數(shù)參數(shù)1 dispatch_once用于檢查代碼塊是否已經(jīng)被調(diào)度的謂詞(其實就是長整形,實際上作為BOOL使用)。
參數(shù)2 希望在程序的生命周期內(nèi)僅被調(diào)用一次的代碼塊(適用于單例)
如果被多個線程同時調(diào)用,該函數(shù)會同步等待 直至代碼塊完成