淺談 iOS 執行緒

Richard_Gao發表於2015-08-08

通常主執行緒和其他執行緒的使用場景

主執行緒一般用於

  • 繪製UI

  • 響應使用者操作等

其他執行緒用於

  • 網路請求

  • 解析網路返回等

Tips: 解壓、開啟 Zip 包,讀寫較大檔案的操作也不宜放在主執行緒裡。

一般非同步網路請求中會有一個 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 能夠訪問該資料結構。

GCD 實踐

預先宣告一個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 和 operation 序列

NSOperations 其實就是基於 GCD 實現的,使用NSOperation 的時候其實也就是在使用 GCD。但是NSOperation 給我們提供了更多更方便的功能,我們可以操作一些 operation,這些operation 依賴於其他 operation。還可以在 submit block 之後重新對 operation queue 進行排序。

Bingo!
之後應該會總結一些關於 GCD 使用的更詳細的文章。

相關文章