多線程-gcd

GCD簡介(Grand Central Dispatch)

GCD是從ios4開始引入的新一代多線程編程技術(shù)

GCD需要用到一個(gè)系統(tǒng)庫lib dispatch,lib dispatch是蘋果的一個(gè)開發(fā)庫,我們在使用時(shí)不需要導(dǎo)入這個(gè)庫 因?yàn)橄到y(tǒng)層也在用這個(gè)庫 所以這個(gè)庫不導(dǎo)入它也會(huì)被加載進(jìn)來

使用GCD開發(fā)者只需要定義想要執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中,GCD就能生成必要的線程并有計(jì)劃的執(zhí)行任務(wù),ios的內(nèi)核會(huì)基于DIspatch Queue中的任務(wù)數(shù)量、CPU核數(shù)和CPU負(fù)荷等當(dāng)前的系統(tǒng)狀態(tài)來決定創(chuàng)建多少個(gè)線程和并發(fā)執(zhí)行多少個(gè)任務(wù)

一、Dispatch Queue(調(diào)度隊(duì)列)

使用GCD進(jìn)行編程,開發(fā)者要做的只是定義想要執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中。調(diào)度隊(duì)列中的任務(wù)按照FIFO(先入先出)的順序進(jìn)行處理,也就是先進(jìn)入的任務(wù)現(xiàn)行處理

二、調(diào)度隊(duì)列分為串行和并發(fā)兩種

串行VS并發(fā)

串行:要求等待正在執(zhí)行的任務(wù)完成,再執(zhí)行下一個(gè),也就是說只會(huì)創(chuàng)建一個(gè)線程來執(zhí)行任務(wù)

并發(fā):隊(duì)列中后面的任務(wù)可以不必等待正在執(zhí)行的任務(wù)完成就可以執(zhí)行,也就是同時(shí)可以執(zhí)行多個(gè)任務(wù),也就是說會(huì)創(chuàng)建多個(gè)線程同時(shí)執(zhí)行多個(gè)任務(wù)

1、串行隊(duì)列

創(chuàng)建一個(gè)隊(duì)列會(huì)開辟一個(gè)分線程,添加到串行隊(duì)列中的任務(wù)在新線程中會(huì)按照添加的順興執(zhí)行。串行隊(duì)列經(jīng)常處理一些需要順序訪問的任務(wù)。創(chuàng)建多個(gè)串行隊(duì)列,多個(gè)串行隊(duì)列間是并行的。

創(chuàng)建串行隊(duì)列代碼如下

/**

*? @author沈超, 16-07-15 14:07:33

*

*創(chuàng)建串行隊(duì)列,添加到此隊(duì)列的任務(wù)回一個(gè)挨著一個(gè)執(zhí)行此隊(duì)列會(huì)開辟一條線程執(zhí)行任務(wù)

*

*? @param "com.cmcc.serialQueue"唯一標(biāo)識符,一般域名反寫+隊(duì)列名,用于調(diào)試,崩潰報(bào)告中查看

*? @param NULL指定創(chuàng)建queue的類型,NULL或DISPATCH_QUEUE_SERIAL表示串行隊(duì)列

*

*? @return <#return value description#>

*/

dispatch_queue_tserial_Queue=dispatch_queue_create("com.cmcc.serialQueue",NULL);/**

*? @author沈超, 16-07-15 14:07:10

*

*創(chuàng)建并發(fā)隊(duì)列,添加到此隊(duì)列的任務(wù)會(huì)并發(fā)執(zhí)行,此隊(duì)列會(huì)創(chuàng)建多個(gè)線程執(zhí)行任務(wù)

*

*? @param "com.cmcc.concurrent_queue"唯一標(biāo)識符,一般域名反寫+隊(duì)列名,用于調(diào)試,崩潰報(bào)告中查看

*? @param DISPATCH_QUEUE_CONCURRENT指定創(chuàng)建queue的類型,DISPATCH_QUEUE_SERIAL表示并發(fā)隊(duì)列

*

*? @return <#return value description#>

*/

dispatch_queue_tconcurrent_queue=dispatch_queue_create("com.cmcc.concurrent_queue",DISPATCH_QUEUE_CONCURRENT);

三、系統(tǒng)提供隊(duì)列全局隊(duì)列和主隊(duì)列

①全局隊(duì)列

全局隊(duì)列是一個(gè)在全局都可以獲取的并發(fā)隊(duì)列,而是只需要獲取全局隊(duì)列使用即可。全局隊(duì)列有四種,即4個(gè)優(yōu)先級,分別是high、default、low、background

獲取全局隊(duì)列的代碼如下

dispatch_queue_t dispatch_global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

②主隊(duì)列

主隊(duì)列是一個(gè)在全局都可以獲取的串行調(diào)度隊(duì)列,該隊(duì)列中的任務(wù)都是在主線程中執(zhí)行的。因?yàn)槭窃谥骶€程中執(zhí)行,所以一般會(huì)將用戶界面更新等一些必須在主線程中執(zhí)行的任務(wù)追加帶主隊(duì)列中。

獲取主隊(duì)列代碼如下

dispatch_queue_tmain_queue =dispatch_get_main_queue();

隊(duì)列類型

創(chuàng)建的串行隊(duì)列

創(chuàng)建的并發(fā)隊(duì)列

獲取的全局隊(duì)列

獲取的主隊(duì)列

四、dispatch_async 和 dispatch_sync

任務(wù):定義想要執(zhí)行的任務(wù) 使用block語法來完成

同步提交:dispatch_sync同步添加任務(wù)到隊(duì)列中,它是等待任務(wù)完成之后再繼續(xù)執(zhí)行。

異步提交:dispatch_async異步添加任務(wù)到異步隊(duì)列中,它不會(huì)做任何等待

注意:同步提交不管提交到哪個(gè)什么隊(duì)列,不會(huì)開辟新線程,在當(dāng)前線程中執(zhí)行

特別注意:同步提交要慎重使用,尤其是在當(dāng)前隊(duì)列中同步提交任務(wù)到當(dāng)前隊(duì)列,會(huì)造成線程死鎖

五、dispatch_group

如果想在dispatch_queue中所有的任務(wù)執(zhí)行完成后再做某種操作,在串行隊(duì)列中,可以把該操作放到最后一個(gè)任務(wù)執(zhí)行完成后執(zhí)行,但是在并行隊(duì)列中怎么做呢,這就有了dispatch_group成組操作

創(chuàng)建一個(gè)group

使用dispatch_group_async向組中添加隊(duì)列和任務(wù)

當(dāng)并行隊(duì)列中的任務(wù)執(zhí)行完時(shí),使用dispatch_group_notify執(zhí)行block通知group中的任務(wù)執(zhí)行完畢

六、dispatch_semaphore

dispatch_semaphore信號量記憶計(jì)數(shù)器的一種多線程同步機(jī)制,在多線個(gè)線程訪問共有資源時(shí)候,會(huì)因?yàn)槎嗑€程的特性而引發(fā)數(shù)據(jù)出錯(cuò)的問題。

GCD中有3個(gè)信號量有關(guān)的操作:

dispatch_semaphore_create ? ? 信號量創(chuàng)建

dispatch_semaphore_wait ? ? ? ? 信號量等待 wait會(huì)阻塞線程并且檢測信號量的值,直到信號量值大于0才會(huì)往下執(zhí)行,

同時(shí)對信號量執(zhí)行-1操作

dispatch_semaphore_signal ? ? 發(fā)送通知+1 如果信號量值小于0直接喚醒線程繼續(xù)執(zhí)行

場景1:并發(fā)隊(duì)列中的兩個(gè)操作 操作1完成后操作2才能開始(線程間通信)

場景2:控制并發(fā)隊(duì)列中并發(fā)任務(wù)數(shù)量

七、dispatch_once

使用Dispatch_once函數(shù)實(shí)現(xiàn)單例中的線程同步

該函數(shù)參數(shù)1 dispatch_once用于檢查代碼塊是否已經(jīng)被調(diào)度的謂詞(其實(shí)就是長整形,實(shí)際上作為BOOL使用) 加static使用靜態(tài)變量 以保證只執(zhí)行一次。

參數(shù)2 希望在程序的生命周期內(nèi)僅調(diào)用一次的代碼塊(適用于單例)如果被多個(gè)線程同時(shí)調(diào)用,該函數(shù)會(huì)同步等待,直至代碼塊完成

優(yōu)勢:

1、線程安全

2、僅需要少量代碼塊實(shí)現(xiàn)單例

八、dispatch_barrier_async

在并發(fā)隊(duì)列中,使用dispatch_barrier_async添加的任務(wù),隊(duì)列在執(zhí)行此任務(wù)時(shí),隊(duì)列中的其他任務(wù)不會(huì)執(zhí)行,執(zhí)行完成后該隊(duì)列回復(fù)原有執(zhí)行狀態(tài),繼續(xù)并發(fā)執(zhí)行

當(dāng)一系列的操作都需要依賴于某個(gè)操作時(shí),使用dispatch_barrier_async

注意:使用用戶創(chuàng)建的并發(fā)隊(duì)列(在系統(tǒng)隊(duì)列中阻塞無效,等價(jià)于dispatch_async)

九、Dispatch_apply

Dispatch_apply是Dispatch_sync和dispatch_group的關(guān)聯(lián)API。

dispatch_apply函數(shù)值將指定次數(shù)的指定任務(wù)(block)添加到queue中(此處queue一般為并發(fā)隊(duì)列)

dispatch_apply是同步函數(shù),會(huì)阻塞當(dāng)前線程直到所有循環(huán)中任務(wù)執(zhí)行完成,這些任務(wù)在queue中的執(zhí)行順序是不確定的(要并發(fā),要提高效率)

十、Dispatch_after&&dispatch_time

Tips:

并發(fā)VS并行

并發(fā)指的是同時(shí)執(zhí)行了多個(gè)任務(wù),在多個(gè)任務(wù)間切換,一般是指同一時(shí)間間隔同時(shí)執(zhí)行了多個(gè)任務(wù)(一般指單核)

并行值的是同時(shí)執(zhí)行多個(gè)任務(wù),一般是指同一時(shí)刻同時(shí)執(zhí)行了多少任務(wù)(一般指多核)

并行:(多核)

cpu1:任務(wù)part1

thread:_________________

cpu2:任務(wù)part2

thread:_________________

并發(fā):(單核)

thread1— ? — ? ?— ? ?— ? ?— ? ?— ? — ? —任務(wù)part1

thread2 ? — ? — ? ?— ? ?— ? ?— ? ?— ? ?— ? —任務(wù)part2

并行要求并發(fā),并發(fā)并不能保證并行(單核)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容