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