GCD相關(guān)

本文是自己寫的總結(jié)GCD的Demo的結(jié)果??偨Y(jié)的過程中,參考了很多文章,文章底部有引用鏈接,在此感謝。
多圖,流量慎點??。

  • 概念介紹
  • 隊列的創(chuàng)建
  • 任務的創(chuàng)建與執(zhí)行
  • 實踐運用
  • 其他

概念介紹

進程和線程
進程(process):一個執(zhí)行中程序的實例。指的是一個正在運行中的可執(zhí)行文件。每個進程都擁有獨立的虛擬內(nèi)存空間和系統(tǒng)資源,包括端口權(quán)限等,而且至少包含一條主線程(或者可以包括任意數(shù)量的子線程)。當一個進程的主線程退出時,這個進程就結(jié)束了。對于iOS的app來說,一個app運行起來,就是一個進程。

進程.png

線程:(thread),指定是一個獨立的代碼執(zhí)行路徑,(代碼執(zhí)行的管道),線程是代碼執(zhí)行路徑的最小單位。

同步和異步
同步和異步操作的主要區(qū)別在于是否等待操作執(zhí)行完成,即是否阻塞當前線程。
同步:在發(fā)出一個同步調(diào)用時 ,在沒有得到結(jié)果之前,該調(diào)用就不返回。
異步:在發(fā)出一個異步調(diào)用后,調(diào)用者不會立刻得到結(jié)果,該調(diào)用就返回了。
同步和異步是針對能不能開線程。同步不能開啟新的線程。異步可以。異步雖然有開啟新線程的能力,但不是說只要異步調(diào)用,就開啟新線程了。
在iOS中,同步和異步即針對以下兩個函數(shù)。

  • 同步函數(shù):
 dispatch_sync(queue, ^{
        
    })
  • 異步函數(shù):
 dispatch_async(queue, ^{
        
    })

串行和并發(fā)
串行和并發(fā)指的是任務(代碼)的執(zhí)行方式。
串行是指多個任務時,各個任務按順序執(zhí)行,挨個兒進行,完成一個之后才能進行下一個。順序不會亂。
并發(fā)指的是多個任務可以同時(一個時間段內(nèi))執(zhí)行。異步是并發(fā)的前提。
在iOS中,任務的執(zhí)行方式(串行或并發(fā)),由隊列來管理。隊列是用來存放任務的。
隊列和線程
在iOS中,有兩種不同類型的隊列:串行隊列(主隊列是一種特殊的串行隊列)和并發(fā)隊列。串行隊列一次只能執(zhí)行一個任務,并發(fā)隊列則可以允許多個任務同時執(zhí)行。iOS系統(tǒng)是使用這些隊列進行任務調(diào)度的 ,系統(tǒng)會根據(jù)調(diào)度任務的需要和系統(tǒng)當前的負載情況動態(tài)的創(chuàng)建和銷毀線程,不需要我們手動管理線程的銷毀。隊列負責任務的執(zhí)行方式;線程是任務的執(zhí)行通道。

  • 串行隊列(Serial Dispatch Queue)
    每次只有一個任務被執(zhí)行。讓任務一個接著一個執(zhí)行。
  • 并發(fā)隊列 (Concurrent Dispatch Queue)
    可以讓多個任務并發(fā)執(zhí)行,在異步調(diào)用的前提下,可以開啟線程,實現(xiàn)并發(fā)。

插個題外話

并發(fā)和并行

  • 并發(fā)只是假象的同時,是單個處理器的計算機的cpu快速的在不同的程序上切換。
  • 并行是真正意義上的同時,是多個處理器的計算機,各個cpu在同一時間執(zhí)行不同的程序。


    并發(fā)

    并行

    題外話插完了


隊列的創(chuàng)建

GCD中有三種隊列:串行隊列,并發(fā)隊列,主隊列(一種特殊的串行隊列)。

//串行隊列創(chuàng)建

 dispatch_queue_t serialQueue = dispatch_queue_create("com.GCDDemo.testSerial", DISPATCH_QUEUE_SERIAL);

//并發(fā)隊列創(chuàng)建
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.GCDDemo.testConcurrent", DISPATCH_QUEUE_CONCURRENT);
創(chuàng)建隊列的函數(shù)有兩個參數(shù),第一個參數(shù)表示隊列的標識符,類似名字的作用,可為空。第二個參數(shù)表示隊列的種類,是串行隊列還是并發(fā)隊列,必填。
除了創(chuàng)建并發(fā)隊列外,還可以直接獲得系統(tǒng)為我們提供的全局并發(fā)隊列。

//獲取全局并發(fā)隊列
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
第一個參數(shù)表示隊列的優(yōu)先級,一般填默認的就可以。第二個參數(shù)是系統(tǒng)預留出來的,填0即可。

//獲取主隊列
dispatch_queue_t mainQueue = dispatch_get_main_queue();

任務的創(chuàng)建與執(zhí)行

//同步執(zhí)行任務創(chuàng)建
dispatch_sync(queue, ^{
    // 任務代碼
});

//異步函數(shù)執(zhí)行任務創(chuàng)建
 dispatch_async(queue, ^{
        //任務代碼
    });
上邊函數(shù)的block塊里是一個任務。

因為有兩種調(diào)用創(chuàng)建任務的函數(shù)和兩種隊列,再加上一種特殊的主隊列。所以我們就一共有六種情況,不同的組合跑出來的效果不一樣,先看下這六種組合的區(qū)別。

并發(fā)隊列 串行隊列 主隊列
同步 (sync) 沒有開啟新線程,串行執(zhí)行任務 沒有開新線程,串行執(zhí)行任務 如果在主線程中調(diào)用:會出現(xiàn)死鎖,不執(zhí)行。在其他線程中調(diào)用:沒有開新線程,串行執(zhí)行任務
異步(async) 會開啟新線程,并發(fā)執(zhí)行任務 會開啟一條新線程,串行執(zhí)行任務 沒有開啟新線程,串行執(zhí)行任務

實踐運用

以下測試中所用到的并發(fā)隊列都用系統(tǒng)提供的全局并發(fā)隊列

  • 同步調(diào)用+并發(fā)隊列
    同步并發(fā)代碼.png
同步并發(fā)主.png

從運行結(jié)果中可以看出,同步函數(shù)調(diào)用,沒有開線程,任務都是在主線程進行,而且是順序串行執(zhí)行?!驹谥骶€程中運行該方法】

同步并發(fā)子.png

在子線程中運行的話,也一樣是沒有開新的線程,所有任務都是按照順序串行執(zhí)行。

  • 同步調(diào)用+串行隊列
同步串行.png
同步串行主線程.png

主線程中: 同步串行,沒有開啟新線程,所有任務都要按照屬性串行執(zhí)行,【當前同步函數(shù)的調(diào)用,必須等到調(diào)用的函數(shù)執(zhí)行結(jié)束后(即需要將block塊里的任務執(zhí)行完),才能進行下一步】

同步串行子線程.png

子線程中,依然是沒有開啟新的線程。所有任務都是按照順序串行執(zhí)行。

  • 異步調(diào)用+并發(fā)隊列
    異步并發(fā)代碼.png
異步并發(fā)主.png

從運行結(jié)果來看,結(jié)束是先于函數(shù)調(diào)用block里的任務打印出來,說明異步調(diào)用,不需要函數(shù)(dispatch_async)返回,繼續(xù)往下執(zhí)行,從運行結(jié)果的線程number來看,開了三條子線程,而且不同的任務分別在不同的線程中執(zhí)行。說明異步并發(fā)開啟子線程。

異步并發(fā)子.png

在子線程中調(diào)用異步并發(fā),依然會開啟新的子線程。

  • 異步+串行隊列
異步串行代碼.png
異步串行主.png

異步串行在主線程中運行,開啟了一條新的線程執(zhí)行調(diào)用函數(shù)中加的任務。

異步串行子.png

在子線程中執(zhí)行方法,也會開一條新的子線程執(zhí)行函數(shù)調(diào)用中block中任務。

  • 同步調(diào)用+主隊列
同步主隊列 主線程.png

程序崩潰 主線程中的任務是在主隊列中的,主隊列是串行隊列 ,任務需要一個個按照順序執(zhí)行。在主線程中調(diào)用了同步函數(shù),這就相當于隊列中加了一個任務1,同步函數(shù)的block里又往主隊列里加了任務2。主隊列中的任務需要依次執(zhí)行。所以任務2的執(zhí)行,需要任務1執(zhí)行完成(同步函數(shù)的調(diào)用返回)。但是任務1的調(diào)用返回必須得block塊里的代碼(即任務2)執(zhí)行完畢才可以。所以兩者相互等待,造成死鎖?!具@里有點繞,不知道自己說的是否清楚??】

同步主隊列 子.png

如果再子線程里調(diào)用該方法,程序就能按照串行執(zhí)行。不會崩潰。

由上可以得出死鎖發(fā)生的條件
1,隊列是串行隊列。2,調(diào)用同步函數(shù)將任務加到自己的隊列中。

  • 異步調(diào)用+主隊列
    異步主隊列代碼.png
異步主隊列主.png

雖然是異步,但是也沒有開啟子線程,調(diào)用函數(shù)的任務都在主線程中執(zhí)行。

異步主隊列 子.png

在子線程中,也沒有開啟新的線程。

  • 線程間通信,從子線程回到主線程。
    通信.png

    一般會在子線程做耗時工作,任務結(jié)束后,回到主線程更新UI。

其它方法

隊列組
隊列組通知代碼.png
隊列組通知結(jié)果.png
隊列組enter:leave代碼.png
隊列組enter:leave結(jié)果.png
隊列組wait代碼.png
隊列組wait結(jié)果.png

柵欄函數(shù)
柵欄代碼.png
柵欄結(jié)果.png

柵欄函數(shù),顧名思義,通過柵欄將上下的代碼隔開,真正的運行效果也是隔開了。【我開發(fā)中沒有用到過這個函數(shù)。不清楚用處】

延遲執(zhí)行
延遲執(zhí)行.png
一次執(zhí)行(單例)

說到單例,這里有篇談weak關(guān)鍵字的文章,延伸閱讀:弱引用單例

一次代碼.png

信號量

信號量
GCD中信號量有關(guān)的有三個函數(shù)。

//創(chuàng)建信號量 參數(shù):信號量的初始值。
dispatch_semaphore_t  semaphore = dispatch_semaphore_create(0);
//將信號量減一  參數(shù):信號量,等待時間
// 等待降低信號量,如果代碼執(zhí)行到這里,信號量的值=0,則阻塞當前線程,知道信號量值大于0時,才會進行執(zhí)行這里,同時將信號量減一。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//信號量加一。
dispatch_semaphore_signal(semaphore);
  • 1,線程同步

    信號量線程同步.png
    從圖中運行結(jié)果來看,異步并發(fā)操作,調(diào)用異步函數(shù)時,應該不用等待該函數(shù)返回,直接打印結(jié)束。但是在這里加了信號量的控制。當走到dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);時,信號量為0,此時線程阻塞,直到信號量大于0;dispatch_semaphore_signal(semaphore);當走到該行代碼時,信號量加1,信號量等待處開始執(zhí)行。

  • 2,控制最大并發(fā)數(shù)(這個需求用NSOperationQueue會更方便實現(xiàn)。)

總結(jié): 一直想把一些東西總結(jié)下來,有的時候看到了,覺得懂了,但是到用的時候卻不是。經(jīng)過這次的總結(jié),也發(fā)現(xiàn)了一些問題,之后會陸續(xù)更新。作為記錄,也希望能給需要的人以參考,如果有問題,歡迎指出。謝謝????。
最后,再次強調(diào)下:Demo傳送門 ????????歡迎star

參考:http://blog.csdn.net/sinat_35512245/article/details/53836580
http://www.itdecent.cn/p/2d57c72016c6
http://blog.csdn.net/fern_girl/article/details/61197995
http://www.cnblogs.com/kenshincui/p/3983982.html#3913461

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

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

  • 多線程學習筆記-GCD 我把這篇文章所用到的代碼總結(jié)到這里->GCD項目總結(jié)下載地址-GCD-wxk可以下載參考 ...
    wxkkkkk閱讀 573評論 0 2
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,911評論 1 17
  • 心有所想就有欲望,有欲望并不是壞事。欲望過甚就會變苦,求不得苦從此而來。然而這種時候其實就是你修行的時候,有的時候...
    睡一夜就餿星人閱讀 401評論 0 1
  • 最近的生活充滿了刺激,總是忽然看到非常吸引的消息卻:1、過了申請的截止日期;2、即將過截止日期;3、懷著激動的心情...
    lxt閱讀 338評論 0 1
  • 感恩19大會議召開!各個行業(yè),各個階層的人們都在慶祝19大,希望19大的召開能為人們帶來切實的利益,也希望我們的祖...
    武丹yoyo閱讀 444評論 0 2

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