66 GCD

轉載:http://blog.csdn.net/crycheng/article/details/22214617

一:
GCD提供很多超越傳統多線程編程的優勢:
易用: GCD比之thread跟簡單易用。由于GCD基于work unit而非像thread那樣基于運算,所以GCD可以控制諸如等待任務結束、監視文件描述符、周期執行代碼以及工作掛起等任務。基于block的血統導致它能極為簡單得在不同代碼作用域之間傳遞上下文。
效率: GCD被實現得如此輕量和優雅,使得它在很多地方比之專門創建消耗資源的線程更實用且快速。這關系到易用性:導致GCD易用的原因有一部分在于你可以不用擔心太多的效率問題而僅僅使用它就行了。
性能: GCD自動根據系統負載來增減線程數量,這就減少了上下文切換以及增加了計算效率。
二:Dispatch Queues
GCD的基本概念就是dispatch queue。dispatch queue是一個對象,它可以接受任務,并將任務以先到先執行的順序來執行。dispatch queue可以是并發的或串行的。并發任務會像NSOperationQueue那樣基于系統負載來合適地并發進行,串行隊列同一時間只執行單一任務。
GCD中有三種隊列類型:
The main queue: 與主線程功能相同。實際上,提交至main queue的任務會在主線程中執行。main queue可以調用dispatch_get_main_queue()來獲得。因為main queue是與主線程相關的,所以這是一個串行隊列。
Global queues: 全局隊列是并發隊列,并由整個進程共享。進程中存在三個全局隊列:高、中(默認)、低三個優先級隊列??梢哉{用dispatch_get_global_queue函數傳入優先級來訪問隊列。
用戶隊列(自定義隊列): 用戶隊列 (GCD并不這樣稱呼這種隊列, 但是沒有一個特定的名字來形容這種隊列,所以我們稱其為用戶隊列) 是用函數 dispatch_queue_create 創建的隊列. 這些隊列是串行的。正因為如此,它們可以用來完成同步機制, 有點像傳統線程中的mutex。
Dispatch Queues的生成可以有這幾種方式:  
  
1. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_SERIAL); //生成一個串行隊列,隊列中的block按照先進先出(FIFO)的順序去執行,實際上為單線程執行。第一個參數是隊列的名稱,在調試程序時會非常有用,所有盡量不要重名了。  
  
2. dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); //生成一個并發執行隊列,block被分發到多個線程去執行  
  
3. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //獲得程序進程缺省產生的并發隊列,可設定優先級來選擇高、中、低三個優先級隊列。由于是系統默認生成的,所以無法調用dispatch_resume()和dispatch_suspend()來控制執行繼續或中斷。需要注意的是,三個隊列不代表三個線程,可能會有更多的線程。并發隊列可以根據實際情況來自動產生合理的線程數,也可理解為dispatch隊列實現了一個線程池的管理,對于程序邏輯是透明的。  
  
官網文檔解釋說共有三個并發隊列,但實際還有一個更低優先級的隊列,設置優先級為DISPATCH_QUEUE_PRIORITY_BACKGROUND。Xcode調試時可以觀察到正在使用的各個dispatch隊列。  

4. dispatch_queue_t queue = dispatch_get_main_queue(); //獲得主線程的dispatch隊列,實際是一個串行隊列。同樣無法控制主線程dispatch隊列的執行繼續或中斷。  
  
接下來我們可以使用dispatch_async或dispatch_sync函數來加載需要運行的block。  
  
dispatch_async(queue, ^{  
  
  //block具體代碼  
  
}); //異步執行block,函數立即返回  
  
dispatch_sync(queue, ^{  
  
  //block具體代碼  
  
}); //同步執行block,函數不返回,一直等到block執行完畢。編譯器會根據實際情況優化代碼,所以有時候你會發現block其實還在當前線程上執行,并沒用產生新線程。  
  
實際編程經驗告訴我們,盡可能避免使用dispatch_sync,嵌套使用時還容易引起程序死鎖。  
  
如果queue1是一個串行隊列的話,這段代碼立即產生死鎖:  
  
   dispatch_sync(queue1, ^{  
  
      dispatch_sync(queue1, ^{  
  
    ......  
  
  });  
  
  ......  
  
 });   
  
那實際運用中,一般可以用dispatch這樣來寫,常見的網絡請求數據多線程執行模型:  
  
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
  
  //子線程中開始網絡請求數據  
  
  //更新數據模型  
  
  dispatch_sync(dispatch_get_main_queue(), ^{  
  
    //在主線程中更新UI代碼  
  
  });  
  
});  
  
程序的后臺運行和UI更新代碼緊湊,代碼邏輯一目了然。  

dispatch隊列是線程安全的,可以利用串行隊列實現鎖的功能。比如多線程寫同一數據庫,需要保持寫入的順序和每次寫入的完整性,簡單地利用串行隊列即可實現:  
  
dispatch_queue_t queue1 = dispatch_queue_create("com.dispatch.writedb", DISPATCH_QUEUE_SERIAL);  
  
- (void)writeDB:(NSData *)data  
  
{  
  
  dispatch_async(queue1, ^{  
  
    //write database  
  
  });  
  
}   
  
下一次調用writeDB:必須等到上次調用完成后才能進行,保證writeDB:方法是線程安全的。   
dispatch隊列還實現其它一些常用函數,包括:  
  
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t)); //重復執行block,需要注意的是這個方法是同步返回,也就是說等到所有block執行完畢才返回,如需異步返回則嵌套在dispatch_async中來使用。多個block的運行是否并發或串行執行也依賴queue的是否并發或串行。  
  
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); //這個函數可以設置同步執行的block,它會等到在它加入隊列之前的block執行完畢后,才開始執行。在它之后加入隊列的block,則等到這個block執行完畢后才開始執行。  
  
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); //同上,除了它是同步返回函數  
  
void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block); //延遲執行block  
  
最后再來看看dispatch隊列的一個很有特色的函數:  
  
void dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue);  
  
它會把需要執行的任務對象指定到不同的隊列中去處理,這個任務對象可以是dispatch隊列,也可以是dispatch源(以后博文會介紹)。而且這個過程可以是動態的,可以實現隊列的動態調度管理等等。比如說有兩個隊列dispatchA和dispatchB,這時把dispatchA指派到dispatchB:  
  
dispatch_set_target_queue(dispatchA, dispatchB);  
  
那么dispatchA上還未運行的block會在dispatchB上運行。這時如果暫停dispatchA運行:  
  
dispatch_suspend(dispatchA);  
  
則只會暫停dispatchA上原來的block的執行,dispatchB的block則不受影響。而如果暫停dispatchB的運行,則會暫停dispatchA的運行。 
  
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容