多線程之GCD

GCD,Grand Central Dispatch,iOS中常用的多線程技術,GCD提供C風格的API,相對NSOperationQueue以及NSThread,它更加的簡單易用且功能強大.

注意:現(xiàn)在dispatc_group_t,dispatch_queue_t, dispatch_semaphore_t等已經(jīng)被ARC管理,無需要手動release.

隊列 dispatch_queue_t

GCD提供兩種隊列Serial Dispatch Queue(串行隊列),Concurrent Dispatch Queue(并發(fā)隊列). 使用APIdispatch_queue_create創(chuàng)建.

 dispatch_queue_t requestHeaderModificationQueue = dispatch_queue_create("requestHeaderModificationQueue", DISPATCH_QUEUE_CONCURRENT);

第一個參數(shù)為隊列的名字, 也可以寫為NULL,不過為了調(diào)試推薦指定對列名字.
第二個參數(shù)為DISPATCH_QUEUE_CONCURRENTDISPATCH_QUEUE_SERIAL,用于指定隊列的類型.

dispatch_async(requestHeaderModificationQueue, ^{
           .........
        });
dispatch_release(requestHeaderModificationQueue);

GCD的隊列,必須由程序員手動進行引用計數(shù)的管理,當隊列需要釋放的時候,要手動的調(diào)用dispatch_release. 上面的代碼不會立即釋放隊列,因為block強引用了requestHeaderModificationQueue,會等block中的任務執(zhí)行完畢才會釋放隊列.

同時GCD提供dispatch_get_main_queue()dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)可以便捷的獲取主線程和后臺線程.

向隊列中追加任務 dispatch_async和dispatch_sync

dispatch_async(requestHeaderModificationQueue, ^{
           .........
        });
dispatch_sync(requestHeaderModificationQueue, ^{
           .........
        });

使用dispatch_async和dispatch_sync向隊列中追加任務.
dispatch_async.異步執(zhí)行,并不會阻塞當前的線程,而是立即向下執(zhí)行.
dispatch_sync同步執(zhí)行,會阻塞當前線程,等待block中的任務執(zhí)行完畢,程序才會繼續(xù)向下執(zhí)行. 所以要避免在主線程中使用dispatch_sync

disaptch_after

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       ...
    });

上面的代碼意思為在5秒后執(zhí)行block中的任務.
dispatch_after 函數(shù)接受三個參數(shù)
1.第一個參數(shù)是指定時間,用的是 dispatch_time_t 類型的值. 使用dispatch_time 或者 dispatch_walltime函數(shù)生成.
dispatch_time函數(shù)能夠獲取從第一個參數(shù)dispatch_time_t類型的值,到第二個參數(shù)指定的毫秒單位時間后的時間. 如上例,第二個參數(shù)為5 * NSEC_PER_SEC毫秒也就是5秒.

2.第二個參數(shù)指定要追加任務的隊列.

dispatch_group

 dispatch_group_t group = dispatch_group_create()

使用函數(shù)dispatch_group_create創(chuàng)建.
dispatch_group同樣需要程序員手動的管理引用計數(shù). 同dispatch_queue.
dispatch_group同樣有同步執(zhí)行和異步執(zhí)行兩個函數(shù):dispatch_group_asyncdispatch_group_sync.

dispatch_group_async(<#dispatch_group_t  _Nonnull group#>, <#dispatch_queue_t  _Nonnull queue#>, <#^(void)block#>)

比起dispatch_queue的對出一個參數(shù),指定該block屬于指定的dispatch_group_t.

dispatch_group_notify

如果存在多個任務或者多個隊列,想要在所有的任務執(zhí)行完成后,執(zhí)行指定的操作,可以使用dispatch_group_notify.
dispatch_group_notify會監(jiān)聽指定的group,在所有任務執(zhí)行完成后,將指定的任務加入指定的隊列中.

dispatch_queue_t queue = dispatch_queue_create("xxx.aaa.ccc", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
      // ...
    });
    
    dispatch_group_async(group, queue, ^{
       // ...
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
    });
    

dispatch_group_notify

dispatch_group_wait

long result = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
    if (result == 0) {
        NSLog(@"group全部執(zhí)行");
    }else{
         NSLog(@"group并沒有全部執(zhí)行");
    }

一般來說,線程有三個狀態(tài).

  1. 運行,running,此刻線程正在運行
  2. 等待,waiting,此刻線程正在等待某一時間發(fā)生,無法執(zhí)行.
  3. 就緒,ready,此刻線程可以立即執(zhí)行,但是cpu已經(jīng)被占用.


    thread_transform.png

操作系統(tǒng)按照優(yōu)先級或者平均分配給每個線程執(zhí)行時間. 當該線程分配的時間片未用完之前,線程開始等待某事件, 它就會等待狀態(tài). 每當一個線程離開運行狀態(tài)時,操作系統(tǒng)會選擇一個其他的就緒線程立即執(zhí)行.

dispatch_group_wait函數(shù)會使當前線程處于等待狀態(tài),并不返回.直到指定的group中的任務全部完成或者指定的時間到達后. 如上例子,group任務全部完成或者5秒之后,函數(shù)返回,如果group中的任務全部完成,將會返回0 ,否則返回非0.

當時間指定為DISPATCH_TIME_FOREVER意為永久等待,直到group中的任務全部完成.

dispatch_barrier_sync

dispatch_barrier_sync(queue, ^{
        ...
    });

dispatch_barrier_sync可以理解為柵欄函數(shù),在該block加入隊列前加入queue的任務全部執(zhí)行完之后再去執(zhí)行該任務. 然后才會執(zhí)行后面加入的任務. 像一個柵欄一樣,把前后的任務隔離開. 可以用來在并發(fā)隊列中控制任務順序.

dispatch_suspend和dispatch_resume

隊列的掛起以及恢復.

dispatch_semaphore_t

在使用并發(fā)隊列執(zhí)行多個任務時,任務的完成時間以及順序并不能控制,可以使用dispatch_barrier_syncdispatch_group_notify. 這里還有另外一個方法,那就是dispatch_semaphore_t
Dispatch Semaphore 是持有計數(shù)的信號,該計數(shù)是多線程編程中的計數(shù)類型的信號. 在Dispatch Semaphore中,計數(shù)為0時等待,計數(shù)為大于或者等于1時信號減去1而不對等待.

 dispatch_semaphore_t semphore = dispatch_semaphore_create(1);

  result = dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
  
  dispatch_semaphore_signal(semphore);

   dispatch_release(semphore);

以以上代碼為例
第一句,創(chuàng)建一個Dispatch Semaphore并且制定信號量為1
第二句,永久等待Dispatch Semaphore的信號量大于0,然后返回.代碼鄉(xiāng)下執(zhí)行.
第三句,執(zhí)行完任務后,將Dispatch Semaphore的計數(shù)值加1
第四句,如果該Dispatch Semaphore結束使用,那么手動釋放.

dispatch_once_t

 static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        <#code to be executed once#>
    });

dispatch_once函數(shù)保證應用程序運行中,即使在多線層環(huán)境下,也只執(zhí)行一次指定的任務.常常用來被使用生成單例.

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

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

  • 很久前的總結,今天貼出來。適合看了就用,很少講解,純粹用法。 目錄 Dispatch Queue dispatch...
    和女神經(jīng)常玩閱讀 780評論 0 3
  • 1. GCD簡介 什么是GCD呢?我們先來看看百度百科的解釋簡單了解下概念 引自百度百科:Grand Centra...
    千尋_544f閱讀 504評論 0 0
  • GCD (Grand Central Dispatch) :iOS4 開始引入,使用更加方便,程序員只需要將任務添...
    池鵬程閱讀 1,440評論 0 2
  • 雪崩。 從山頂爆發(fā)的雪崩挾雷霆之勢呼嘯狂至。 大量積雪急速下滑崩瀉,瞬間早已傾盆而下,強大的氣流沖下山坡,它以極快...
    酷聽聽書閱讀 430評論 0 0
  • 新年開工10件事,也許有你需要的。 01 買個鬧鐘 手機也可以定鬧鐘,但是還是建議買個鬧鐘。因為鬧鐘只是鬧鐘,而手...
    精力滿滿閱讀 916評論 0 0

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