GCD那些事

發表於2016-08-19

一. GCD的介紹

GCD屬於系統級的執行緒管理,在Dispatch queue中執行需要執行的任務效能非常的高。GCD這塊已經開源,地址:http://libdispatch.macosforge.org。GCD中的FIFO佇列稱為dispatch queue,用來保證先進來的任務先得到執行。這裡我們從作用和場景同時分析,看一下到底在哪些地方會使用。單單隻介紹作用的話,可能

二. 常用的GCD

1. dispatch_semaphore_t,dispatch_semaphore_wait,dispatch_semaphore_signal

作用:

在多執行緒下控制多執行緒的併發數目。

  1. 建立訊號量,可以設定訊號量的資源數。0表示沒有資源,呼叫dispatch_semaphore_wait會立即等待。
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  2. 等待訊號,可以設定超時引數。該函式返回0表示得到通知,非0表示超時。dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  3. 通知訊號,如果等待執行緒被喚醒則返回非0,否則返回0。
    dispatch_semaphore_signal(semaphore);
使用場景一:併發佇列

比如現在我每次想執行10個任務。休息兩秒。繼續執行10個任務。可以這麼寫.

使用場景二:非同步佇列中做事,等待回撥後執行某件事

執行結果:

使用場景三:生產者,消費者

執行結果:

2. dispatch_group_t,dispatch_group_notify

用來阻塞一個執行緒,直到一個或多個任務完成執行。有時候你必須等待任務完成的結果,然後才能繼續後面的處理

使用場景一:併發佇列

等價於:

使用場景二:多工執行完成,重新整理UI

需要在主執行緒中執行,比如操作GUI,那麼我們只要將main queue而非全域性佇列傳給dispatch_group_notify函式就行了。

執行結果:

3. dispatch_apply

是同步函式,會阻塞當前執行緒直到所有迴圈迭代執行完成。當提交到併發queue時,迴圈迭代的執行順序是不確定的

執行結果:

4. dispatch_source_set_timer,dispatch_suspend,dispatch_resume,dispatch_source_cancel

眾所周知,定時器有NSTimer,但是NSTimer有如下弊端:

  1. 必須保證有一個活躍的runloop,子執行緒的runloop是預設關閉的。這時如果不手動啟用runloop,performSelector和scheduledTimerWithTimeInterval的呼叫將是無效的
  2. NSTimer的建立與撤銷必須在同一個執行緒操作、performSelector的建立與撤銷必須在同一個執行緒操作。
  3. 記憶體管理有潛在洩露的風險

如果此時不呼叫

是無法停止的。還有持有self,造成物件無法釋放。
所以在此我還是比較推薦用dispatch的timer,無須考慮這些事情

5. dispatch_barrier_async

這裡之前的文章有非常詳細的解釋以及demo在文章後面。可以參考 iOS非同步讀寫總結之NSDictionary,這裡就不去詳細說明了。 注意一下DISPATCH_QUEUE_CONCURRENT(並行佇列)和DISPATCH_QUEUE_SERIAL(序列佇列)即可

6. dispatch_syncdispatch_async

這裡一個是同步,一個是非同步。只要注意一下死鎖的問題就好了。

錯誤場景1: (死鎖)結果無法輸出(呼叫場景限於主執行緒呼叫主執行緒)

原因:
1:dispatch_sync在等待block語句執行完成,而block語句需要在主執行緒裡執行,所以dispatch_sync如果在主執行緒呼叫就會造成死鎖
2:dispatch_sync是同步的,本身就會阻塞當前執行緒,也即主執行緒。而又往主執行緒裡塞進去一個block,所以就會發生死鎖。

錯誤場景2: (死鎖)

7. dispatch_get_global_queue

全域性併發佇列的優先順序

注意:
在實際修改bug的時候發現,global全域性佇列並不會反覆建立新的執行緒,在系統啟動後底層會維護一個執行緒池的概念,一旦用Global的佇列結束,會快取一段時間。因為在測試的時候可以列印出Thread ID。在多執行緒情況下發現一些ThreadID是一樣的,由此得出結論。

8. dispatch_once

9. dispatch_after

三. 總結

這裡是對GCD做總結的同時,突出了一些使用場景。因為在開發過程中,我們不僅僅知道這東西是啥,更要知道什麼時候靈活運用,這裡提供了一些解決思路。關於Block相關的方法可以參考Block那些事.最後歡迎加入QQ群:237305299。一起探討iOS技術問題。

四. Demo下載

Demo

五. 參考連結

  1. 關於dispatch_semaphore的使用
  2. iOS多執行緒中的dispatch_semaphore_t semaphore(dispatch組和訊號量。)
  3. Wait until multiple networking requests have all executed – including their completion blocks
  4. 選擇 GCD 還是 NSTimer ?
  5. 深入理解dispatch_sync