三. GCD的基本使用

一. GCD的核心概念

  1. 什么是CGD

    • GCD, 全稱Grand Central Dispatch, 又稱中樞調度器
    • 他是Apple公司推出的, 使用純C語言編寫的(意味著性能的高效), 為多核的并行運算創建的牛X產物
    • GCD會自動的利用多核的CPU, 達到更快速的調度線程, 更搞笑的執行任務
    • CGD會自動的管理線程的聲明周期, 如創建線程/調度任務/銷毀線程
  2. 核心概念

    • 任務: 線程需要去執行的操作, 方法, 代碼段
    • 隊列: 用于存放任務的容器
    • 任務添加并存放在隊列中, 然后將隊列中的任務, 根據函數調用的不同, 自發的分配給不同的線程去執行
    • 并且任務的取出, 遵循隊列的FIFO原則: 先進先出, 后進后出
  3. 同步和異步

    • 同步: dispatch_sync( queue隊列, block任務 )

      • 同步: 如果當前線程的任務沒有執行完畢, 隊列中的其他任務就會處于等待執行的狀態
      • 同步函數: 同步函數不具備開啟新線程的能力, 他只能在當前的線程中去執行任務(在哪個線程中執行這個函數, 就在那個線程執行所有的任務)
    • 異步: dispatch_async( queue隊列, block任務 )

      • 異步: 當前線程中的任務沒有執行完畢, 其他的線程也可以被調度去執行任務
      • 異步函數: 具備開啟線程的能力, 可以在新的線程中執行任務

二. GCD中的隊列

  1. 并發和串行的概念

    • 并發: 可讓多個任務并發(同時)執行的隊列, 他自動開啟多個線程去執行任務
      • 并發功能只有在異步函數(dispatch_async)下才會生效
    • 串行: 讓隊列中的任務, 按順序一個個地執行, 即一個任務執行完畢后, 在調度執行下一個任務
  2. 并發隊列

    • 創建一個并發隊列:
      dipatch_queue_t queue = dispatch_queue_create("隊列名稱", DISPATCH_QUEUE_CONCURRENT)

    • 獲取全局并發隊列

        dispatch_queue_t queueG = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
        第一個參數: 隊列的優先級, 分為High/Low/Default/Background
        第二個參數: 暫未采用的參數, 始終傳入0
      
    • GCD內部開啟多少條線程, 是根據系統的當前情況自行決定的, 并不是根據任務的數量去開啟對應的線程

  3. 串行隊列

    • 創建一個串行隊列:
      dispatch_queue_t queue = dispatch_queue_create("隊列名稱", DISPATCH_QUEUE_SERIAL)
    • 獲取主隊列
      • 凡是放在主隊列中的任務, 都必須在主線程中執行
      • 主隊列是默認存在的隊列, 并不是手動創建的
      • 主隊列在調度任務之前, 會檢查主線程的狀態, 如果主線程當前正在執行任務, 那么主隊列就會停止調度隊列中的任務

三. 線程. 隊列和函數之間的組合(重要)

  1. 在并發隊列中, 使用異步函數調度任務

    • 任務的執行, 會開啟新的線程

    • 系統自行決定開啟的線程的數量

    • 任務會被分配到不同線程中并發執行

        // 1. 并發隊列,異步函數,每個異步函數開啟了新的線程,并發執行任務
        - (void)conAsync {
            // 1. 創建隊列(并發隊列)
            dispatch_queue_t queue = dispatch_queue_create("隊列名稱", DISPATCH_QUEUE_CONCURRENT);
            
            // 2. 使用函數封裝任務,并把任務添加到隊列中(異步)
            dispatch_async(queue, ^{
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
      
  2. 在并發隊列中, 使用同步函數調度任務

    • 同步函數執行的任務, 并不會開啟新的線程, 都在主線程中執行

    • 所有的任務串行執行

        // 2. 并發隊列,同步函數,不會開啟新的線程,任務按照順序串行執行
        - (void)conSync {
            // 1. 創建普通的并發隊列, 效果與全局并發隊列相同
        //    dispatch_queue_t queue = dispatch_queue_create("adsfa", DISPATCH_QUEUE_CONCURRENT);
            
            // 1.1 創建全局并發隊列
            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
            
            // 2. 封裝任務,并添加到隊列中(同步)
            dispatch_sync(queue, ^{
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
      
  3. 在串行隊列中, 使用異步函數調度任務

    • 異步函數具備開啟子線程的能力, 因此會開啟一條線程, 但是由于是串行隊列, 因此只會開啟一條新線程

    • 所有的任務都在這個新線程中串行執行任務

        // 3. 串行隊列,異步函數,開啟了一條子線程,隊列中的任務是串行執行的
        - (void)serAsync {
            // 1. 創建串行隊列
            dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);
            
            // 2. 使用異步函數封裝任務
            dispatch_async(queue, ^{
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
      
  4. 在串行隊列中, 使用同步函數執行任務

    • 同步函數不具備開啟線程的能力, 因此所有任務是在主線程中執行的

    • 串行隊列中的任務, 是串行執行的

        - (void)serSync {
            // 1. 創建串行隊列
            dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);
            
            // 2. 使用同步函數封裝任務
            dispatch_sync(queue, ^{
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
      
  5. 在主隊列中, 使用異步函數調度任務

    • 異步函數雖然具備開啟線程的能力, 但是由于主隊列中的任務只能在主線程中執行, 因此并不會開啟新的線程

    • 主隊列也屬于串行隊列, 因此任務串行執行

        - (void)mainAsync {
            // 1. 創建主隊列
            dispatch_queue_t queue = dispatch_get_main_queue();
            
            // 2. 使用異步添加任務
            dispatch_async(queue, ^{
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_async(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
      
  6. 在主隊列中, 使用同步函數調度任務重中之重, 常考問題!!!

    • 主隊列中的任務都會放在主線程中執行

    • 主隊列的特性: 如果主線程目前有任務在處理, 處于忙碌狀態, 那么主隊列就會暫停調度任務

    • 同步函數不具備開啟新線程的能力, 因此同步函數的任務也只能在主線程中處理

    • 當第一個同步函數, 放入主線程準備執行的時候, 這時主線程就會進入工作狀態, 并且進入忙碌狀態

    • 這時主隊列察覺到主線程正處于忙碌, 因此就會停止調度任務, 這時任務的調度停止了, 第一個進入主隊列的同步函數也就停止了執行, 此時, 就會出現死鎖狀態, 變現為程序的死機

        - (void)mainSync {
            // 1. 獲取主隊列
            dispatch_queue_t queue = dispatch_get_main_queue();
            NSLog(@"123");
            // 2. 使用同步添加任務
            dispatch_sync(queue, ^{ // 當開始處理第一個任務的時候, 主線程就已經掛掉了
                NSLog(@"1---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"2---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"3---%@", [NSThread currentThread]);
            });
            
            dispatch_sync(queue, ^{
                NSLog(@"4---%@", [NSThread currentThread]);
            });
        }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容