? GCD是異步執行任務的技術之一。開發者只需要定義想執行的任務并追加到適當的Dispatch Queue中,GCD就能生成必要的線程并計劃執行任務。由于線程管理是作為系統中的一部分來實現的,因此可統一管理,也可執行任務,這樣就比以前的線程更有效率。相比于其他的多線程方法,GCD提供的系統級線程管理提高執行效率。
? GCD的API
? 開發者要做的只是定義想執行的任務并追加到適當的Dispatch Queue 中。
? Dispatch Queue 是執行處理的等待隊列。通過dispatch_async函數等API,在Block語法中寫下想要執行的處理并將其追加到Dispatch Queue。Dispatch Queue按照追加的順序(先進先出FIFO,First-In-First-Out)執行處理。在執行處理時存在兩種Dispatch Queue,一種是等待現在執行中處理的Serial Dispatch Queue(串行執行),另一種是不等待執行中處理的Concurrent Dispatch Queue(并行執行)。一般來說,只在為了避免多線程更新相同數據時導致數據競爭時使用Serial Dispatch Queue。
? dispatch_queue_create
? 通過此函數來生成Dispatch Queue
? dispatch_queue_t ? myDispatchQueue = dispatch_queue_create("? ", );
? 該函數第一個參數指定Dispatch Queued的名稱沒有也可以設為NULL,設置一個好的名稱在調試的時候會很快的定位問題的所在。
? 第二個參數是指定類型,Serial Dispatch Queue時則設置為NULL,如果為Concurrent Dispatch Queue時則設置為DISPATCH_QUEUE_CONCURRENT。
? 注意,在使用此函數生成Dispatch Queue時必須由我們手動進行釋放。這是因為Dispatch Queue沒有具有作為Object-C對象來處理的技術。在使用結束后通過
? dispatch_release(myDispatchQueue);來進行釋放
? Main Dispatch Queue/Global Dispatch Queue
? 在實際的應用中不用特意的生成Dispatch Queue,系統也會給我們提供幾個。那就是Main Dispatch Queue 和 Global Dispatch Queue。
? Main Dispatch Queue是在主線程中執行的Dispatch Queue。因為只有這一個主線程,自然這個就是串行線程了。
? Global Dispatch Queue是所有應用程序都可以用的Dispatch Queue,直接獲取就可以了。這個是并行線程。
? 獲取方法:
? dispatch_queue_t main = dispatch_get_main_queue();
? dispatch_queue_t global = dispatch_get_global_queue(? ,? );
? 第一個參數指明了Global Dispatch Queue的執行優先級,一共有四個DISPATCH_QUEUE_PRIORITY_HIGH(最高優先級),DISPATCH_QUEUE_PRIORITY_DEFAULT(默認優先級)
,DISPATCH_QUEUE_PRIORITY_LOW(低優先級),DISPATCH_QUEUE_PRIORITY_BACKGROUND(后臺優先級)
? //在默認優先級的Global Dispatch Queue中執行Block
? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT),^
? {
?????? //可執行的處理
?????? //在Main Dispatch Queue中執行Block
?????? disptach_async(dispatch_get_main_queue(),^
?????? {
??????????? //只能在主線程中執行的處理
?????? });
? });
? dispatch_set_target_queue
? 指定線程變更優先級。
? dispatch_set_target_queue(? ,? );
? 第一個參數為需要變更優先級的線程,第二個參數為變更目標線程。
? dispatch_after
? 這個函數可以用來實現需要指定時間后進行處理的情況。但是要注意的是,這個并不一定能指定時間后執行處理,而只是在指定時間后追加需處理的代碼塊到Dispatch Queue。所以理論上最快是一添加就立馬處理,但不一定每次都是,對于時間有嚴格要求的并不適用。
? dispatch_time_t? time = dispatch_time(DISPATCH_TIME_NOW , 3ull * NSEC_PER_SEC);
? dispatch_after(time,disptach_get_main_queue(),^
? {
????? //可執行的處理
? });
? 第一個參數是指定時間用的dispatch_time_t 類型的值。該類型可用dispatch_time函數或者dispatch_walltime函數來得到。
? 前一個函數是通常用來計算相對時間,后一個則是用來計算絕對時間。例如指定2015年12月23日11時11分11秒。?
? Dispatch Group
? 在使用dispatch_queue_create后需要使用dispatch_release進行釋放,如果有多個需要釋放的話則會比較麻煩。使用Dispatch Group則會比較方便,可以一次全部釋放。
? dispatch_queue_t? queue? =? dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
? dispatch_group_t? group? =? dispatch_group_create();?
? dispatch_group_async(group,queue,^{? NSLog(@"block1") });
? dispatch_group_async(group,queue,^{? NSLog(@"block2") });
? dispatch_group_notify(group,dispatch_get_main_queue(),^{? NSLog(@"done") });
? dispatch_release(group);
? 在追加到Dispatch Queue中的處理全部執行結束時,使用dispatch_group_notify函數會將執行的Block追加到Dispatch Queue中,將第一個參數指定為要監視的Dispatch Group。在追加的全部處理執行結束時,將第三個參數的Block追加到第二個參數的Dispatch Queue中。在dispatch_group_notify函數中不管指定什么樣的Dispatch Queue,屬于Dispatch Group的全部處理在追加NSLog(@"done")時都已執行結束。
? dispatch_barrier_async
? barrier 作為流程控制的一種方式作用在并行環境中,
? 例如有1234四個并行線程,運行時4個任務的完成先后順序是無法保證的。現在12barrier34,則只有在12任務都完成后將barrier中追加的處理完成后會進行34任務,但是12,34這兩塊任務內部完成順序是無法保證的。
? dispatch_barrier_async(queue,^{});
?? dispatch_async/dispatch_sync
? dispatch_async函數是將指定的Block“非同步”的追加到Dispatch Queue中。
? dispatch_sync函數是將指定的Block“同步”追加到指定的Dispatch Queue中。在追加的Block結束前,函數會一直等待處理執行結束。
? 在使用dispatch_sync函數時要注意,因為這個函數有可能會導致程序死鎖。請想清楚后再使用。
? dispatch_apply
? dispatch_apply函數是dispatch_sync函數和Dispatch Group的關聯API。該函數按指定的次數將指定的Block追加到指定的Dispatch Queue中,并等待處理執行結束。
? dispatch_apply(? ,? ,? );
? 第一個參數為重復的次數,第二個參數為追加對象的Dispatch Queue,第三個參數為追加的處理。例如要對NSArray類對象的所有元素執行處理時,不比一個個的編寫for循環。
? dispatch_apply([array count],queue,^(size_t index)
? {
????? NSLog(@"%zu:%@",index,[array objectAtIndex:index]);
? });
? 由于dispatch_apply和dispatch_sync函數相同,會等待處理執行結束,因此推薦在dispatch_async函數中非同步執行dispatch_apply函數。
? dispatch_once
? dispatch_once函數是保證在應用程序執行中只執行一次指定處理的API。在單例的初始化時通常使用這個函數。
? static dispatch_once_t? once;
? dispatch_once(&once,^{});
?