主線程通常用於網絡
繪製UI數據結構
響應用戶操做等異步
其餘線程用於async
網絡請求spa
解析網絡返回等線程
Tips: 解壓、打開 Zip 包,讀寫較大文件的操做也不宜放在主線程裏。code
通常異步網絡請求中會有一個 completionBlock ,這個 completionBlock 是在主線程中被調用的。
因此,可能消耗大量時間的代碼(例如上面提到的處理 Zip 包的方法)也不宜放在這些 block 中。以下面的代碼所示:對象
[request setCompletionBlock:^{ NSLog(@"Zip file downloaded."); NSData *data = [request responseData]; [self processZip:data sourceURL:sourceURL]; // Ack - heavy work on main thread! }];
那麼,若是在blcok 中有數據須要花費大量時間處理,咱們可使用 Grand Central Dispatch(GCD)系統,讓數據在後臺被處理,或者使用GCD在後臺執行這些代碼。簡單來講,若是但願有代碼在後臺執行,只須要調用 dispatch_async,而後把代碼扔進去。
接來下的事就交給 GCD 啦,若是須要,GCD 會建立一個新的線程;或者 GCD 會重用一個已經存在的可用線程。排序
當你調用 dispatch_async 的時候,就是將代碼傳入了一個 dispatch 隊列,這個隊列裏存儲了全部你傳入的 block。隊列
咱們能夠建立本身的 dispatch 隊列(經過 dispatch create 方法),也能夠爲了主線程的到一個特殊的隊列(經過 dispatchgetmainqueue)。
一個 dispatch 隊列(queue)是按次序排設好的,這就意味着隊列中每次只有一個 block 的代碼被執行。這個特性很是方便,咱們能夠用它保護共享數據(shared data)。
關於保護數據的核心思想是:你須要設置好你的代碼,使得一個特定的數據結構只能被一個特定的正在運行的 dispatch 隊列所訪問。由於 dispatch 隊列按次序執行 block,那麼每次就只有一個block 可以訪問該數據結構。
預先聲明一個dispatch_queue,添加一個 dispatch queue 實例
// Add new instance variable dispatch_queue_t backgroundQueue;
關於 dispatch_queue_t 蘋果官方文檔說明:一個 dispatch queue 是一個用來註冊將要被按順序執行的代碼塊的輕量級對象。
建立dispatch queue
backgroundQueue = dispatch_queue_create("com.razeware.imagegrabber.bgqueue", NULL);
初始化前面說聲明的 dispatch queue,並給這個dispatch queue 命名。上面填 null 參數的地方還能夠填 DISPATCHQUEUESERIAL(等同於null)或者 DISPATCHQUEUECONCURRENT。
DISPATCHQUEUESERIAL :按先進先出原則執行 block 的 dispatch 隊列。
DISPATCHQUEUECONCURRENT:執行當前 block 的 dispatch 隊列。雖然該隊列執行的是當前的代碼,咱們也可使用 barrier block 在隊列中建立同步點。
使用剛纔建立的 dispatch queue
(void)process {
dispatch_async(backgroundQueue, ^(void) { [self processHtml]; });
}
本來 - (void)process 中的代碼是直接執行 [self processHtml]; processHTMl 方法阻塞了主線程,而如今經過調用 dispatch_async 咱們可使得 processHtml 在咱們建立的 backgroundQueue 中在後臺運行。
NSOperations 其實就是基於 GCD 實現的,使用NSOperation 的時候其實也就是在使用 GCD。可是NSOperation 給咱們提供了更多更方便的功能,咱們能夠操做一些 operation,這些operation 依賴於其餘 operation。還能夠在 submit block 以後從新對 operation queue 進行排序。
Bingo!以後應該會總結一些關於 GCD 使用的更詳細的文章。