這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。 需要學習的朋友可以通過網盤免費下載pdf版 (先點擊普通下載 再選擇普通用戶就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/ 1.GCD的API 1.1 D ...
這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。
需要學習的朋友可以通過網盤免費下載pdf版 (先點擊普通下載-----再選擇普通用戶就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/
1.GCD的API
1.1 Dispatch Queue
要談GCD,就一定要瞭解Dispatch Queue
(執行處理的等待隊列)。
Dispatch Queue
按照追加的順序(先進先出FIFO,First-In-First-Out)執行處理。
另外在執行處理是存在兩種Dispatch Queue
,一種是等待現在執行中處理的Serial Dispatch Queue
,另一種是不等待現在執行中處理的Concurrent Dispatch Queue
。

1.2 dispatch_queue_create
由於平時在使用時,我們大部分都是使用系統提供的Main Dispatch Queue
和Global Dispatch Queue
。
所以關於dispatch_queue_create
API,這裡只說兩點:
- 通過
dispatch_queue_create
函數生成的Dispatch Queue
在使用結束後要通過dispatch_release
函數釋放。 - 如果生成過多的線程,就會消耗大量記憶體,大幅度降低系統的響應性能。而使用系統提供的
Global Dispatch Queue
則不用擔心這個問題。所以除非必要,其他情況建議使用系統提供的Dispatch Queue
。
1.3 dispatch_set_target_queue
使用dispatch_queue_create
函數生成的Dispatch Queue
,都使用的是與系統提供的Global Dispatch Queue
的預設優先順序相同的優先順序。而要變更生成的執行優先順序的話就要使用dispatch_set_target_queue
函數。
在後臺執行動作處理的Serial Dispatch Queue
的生成方法如下:
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.mySerialDispatchQueue", NULL);
dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackground);
1.3 dispatch_after
dispatch_after
這裡只說一點,dispatch_after
函數並不是在指定時間後執行處理,而只是在指定時間追加處理到Dispatch Queue
。
因為Main Dispatch Queue
在主線程的RunLoop
中執行,所以在比如每隔1/60秒執行的RunLoop
中,Block最快在 3 秒後執行,最慢在 3 秒 + 1/60 秒後執行,並且在Main Dispatch Queue
有大量處理追加或主線程的處理本身有延遲時,這個時間會更長。
所以該函數在有嚴格時間要求的情況下使用會出現問題,但是只是想大致延遲執行處理,該函數是非常有效的。
1.4 dispatch_barrier_async
在訪問資料庫或文件時,使用多線程可能會產生數據競爭的問題,當然使用Serial Dispatch Queue
可避免數據競爭。
但是如果讀取處理只是與讀取處理並行執行,那麼多個並行執行就不會發生問題。也就是說為了高效率的進行訪問,讀取處理追加到Concurrent Dispatch Queue
,寫入處理在任一讀取處理沒有執行的狀態下,追加到Serial Dispatch Queue
中即可(在寫入處理結束之前,讀取處理不可執行)。
使用dispatch_barrier_async
便可解決這個問題。dispatch_barrier_async
函數會等待追加到Concurrent Dispatch Queue
上的並行執行的處理全部結束後,再將制定的處理追加到該Concurrent Dispatch Queue
中。然後在由dispatch_barrier_async
函數追加的處理執行完畢後,Concurrent Dispatch Queue
才恢復為一般的動作,追加到該Concurrent Dispatch Queue
的處理又開始並行執行。
dispatch_async(queue, blk0_for_reading);
dispatch_async(queue, blk1_for_reading);
dispatch_async(queue, blk2_for_reading);
dispatch_async(queue, blk3_for_reading);
dispatch_barrier_async(queue, blk_for_writing);
dispatch_async(queue, blk4_for_reading);
dispatch_async(queue, blk5_for_reading);
dispatch_async(queue, blk6_for_reading);
dispatch_async(queue, blk7_for_reading);
如上所示,使用方法非常簡單。僅使用dispatch_barrier_async
函數代替dispatch_async
函數即可。

1.5 dispatch_apply
dispatch_apply
函數是dispatch_sync
函數和Dispatch Group
的關聯API。該函數按指定的次數將指定的Block追加到指定的Dispatch Queue
中,並等待全部處理執行結束。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zu", index);
});
NSLog(@"done");
例如,該源代碼的執行結果為:
4
1
0
3
5
2
6
8
9
7
done
因為在Global Dispatch Queue
中執行處理,所以各個處理的執行時間不定。但是輸出結果中最後的done必定在最後的位置上。這是因為dispatch_apply
函數會等待全部處理執行結束。
1.6 Dispatch I/O
大家可能想過,在讀取較大文件時,如果將文件分成合適的大小並使用Global Dispatch Queue
併列讀取的話,應該會比一般的讀取速度快不少。能實現這一功能的就是Dispatch I/O
和Dispatch Data
。

如果想提高文件讀取速度,可以嘗試使用Dispatch I/O
。
1.7 Dispatch Source
GCD中出了主要的Dispatch Queue
外,還有不太引人註目的Dispatch Source
。它是BSD系內核慣有功能kqueue
的包裝。
kqueue
是在XNU內核中發生各種事件時,在應用程式編程方執行處理的技術。其CPU負荷非常小,儘量不占用資源。kqueue
可以說是應用程式處理XNU內核中發生的各種事件的方法中最優秀的一種。
Dispatch Source
可以處理一下事件。

在使用NSTimer做定時器的時候,大家應該都知道如果使用不當,會出現記憶體泄漏的問題。
而如果作為一個封裝的組件來說,就需要將NSTimer屬性暴露出來,在控制器銷毀時,調用NSTimer的invalidate方法。如果忘記的話就會記憶體泄漏!
需要IT編程經典書籍資源大合集百度網盤鏈接的加qq 2057904338,另本人願意有償帶小白學python,幫助你答疑解惑,幫助你解決問題,指導你找工作,帶你入行。相信我有人帶著你的話可以少走彎路,成功入行拿高薪。北京地區周六日可上門指導,非北京線上指導。本人前每日優鮮後端工程師,土木專業自學python成功轉行,月薪5位數,性格安靜,誠信正直,想學的加qq。
另閑聊的也可加,就當交個朋友吧!