天天看點

多線程之NSThread、NSOperation及GCD

轉自:http://www.xiaoxiangzi.com/Programme/IOS/5968.html

這篇主要總結下iOS開發中多線程的使用,多線程開發一般使用NSThread、NSOperation及GCD三種方式,常用GCD及NSOperation。

    1.NSThread

      建立線程主要有以下三種方式

多線程之NSThread、NSOperation及GCD

     需要注意的是對于多個線程可能同時通路一個對象的時候,使用“@synchronized”來解決這類線程同步問題。

     在子線程中通知主線程通常使用以下兩種辦法:

多線程之NSThread、NSOperation及GCD

    2.NSOperation

     NSOperation有三種使用方式,分别是NSInvocationOperation、NSBlockOperation以及自定義NSOperation操作,并可對NSOperation設定依賴關系,進而确定任務執行的先後順序,還可以對任務的狀态進行監控甚至控制,以及設定線程最大并發數量等等。

    (1)NSInvocationOperation

      首先是NSInvocationOperation方式建立線程如圖所示,需要注意的是這種方式建立的操作隻有加入到隊列去執行才是異步操作,否則還是在主線程同步執行

多線程之NSThread、NSOperation及GCD
多線程之NSThread、NSOperation及GCD

       加入到隊列自動執行時,會建立線程異步執行

多線程之NSThread、NSOperation及GCD
多線程之NSThread、NSOperation及GCD

    (2)NSBlockOperation

      第二種則是使用NSBlockOperation,同樣需要注意的是當操作的任務數隻有一個時,任務會在目前線程同步執行

多線程之NSThread、NSOperation及GCD

      當任務數大于1的時候,會開啟新線程并異步執行

多線程之NSThread、NSOperation及GCD

       當把NSBlockOperation定義的操作加入到隊列中時,會以異步并發的方式去執行這些任務

多線程之NSThread、NSOperation及GCD

     (3)繼承NSOperation,自定義Operation

       這種方法較為靈活,通過繼承NSOperation并重寫相關方法實作,例如SDWebImage就用到了這種方式。

     (4)設定依賴

       如果任務之間有先後順序依賴,可以對他們設定依賴關系解決這個問題,如圖所示,operation1依賴operation2,而operation2又依賴于operation3,于是執行順序為operation3、operation2、operation1

多線程之NSThread、NSOperation及GCD

     (5)設定任務最大并發數

     可以通過設定maxConcurrentOperationCount限定任務并發數量,避免并發操作消耗太多資源

多線程之NSThread、NSOperation及GCD

    (6)任務狀态的監控以及設定

      可以擷取到任務的執行狀态,是否執行中還是取消了或者完成了等等

多線程之NSThread、NSOperation及GCD

    需要注意的是,發送取消任務的消息,任務并不一定就真的取消,因為加入到隊列以後,任務的執行都是由系統來管理了,取消成功的前提是任務還沒有開始執行,另外需要注意的是即使該任務即使成功取消了,也還是會被系統認定為任務已經完成finished(具體),是以如果有其他任務依賴于已經被取消的任務,需要用“isCancelled”進行判斷,尤其是任務完成回調事件裡做一些操作的話,可能說的有點繞,詳細見下圖:

多線程之NSThread、NSOperation及GCD

      如果不進行判斷,即使operation3已經取消了,由于系統認為取消的任務也算finished,是以operation3的任務完成回調事件仍然觸發

多線程之NSThread、NSOperation及GCD

     更詳細的可以參考Concurrency Programming Guide中這部分的内容

多線程之NSThread、NSOperation及GCD

     當然,還可以直接對整個列進行管理,包括挂起或恢複隊列中所有任務,取消隊列裡所有任務等等

多線程之NSThread、NSOperation及GCD

    3.GCD

    GCD的使用主要有以下幾種方式:

   (1)在主線程中添加任務,dispatch_async異步方式執行,常見使用場景是進入以後,異步加載相關圖檔資訊

多線程之NSThread、NSOperation及GCD

    (2)GCD中解決線程同步的問題可以使用串行隊列,串行隊列裡任務會按照添加順序依次執行,需要注意的是以distpatch_sync同步方式執行任務,所有任務都是在主線程進行的

多線程之NSThread、NSOperation及GCD

    (3)在串行隊列中以dispatch_async異步方式執行任務,則系統開啟一個新線程執行任務

多線程之NSThread、NSOperation及GCD

     (4)在并發隊列中,以dispatch_async異步方式執行任務,則系統會根據任務數量建立一定數量的線程來執行任務,注意這裡用的是全局并發隊列。

多線程之NSThread、NSOperation及GCD

     (5)GCD方式執行延時任務

多線程之NSThread、NSOperation及GCD

     上圖為回到主線程執行延時任務,下圖為開啟新的線程執行延時任務

多線程之NSThread、NSOperation及GCD

     (6)隊列組

      當需要同時執行多個任務,例如同時下載下傳多張圖檔,并對圖檔進行處理顯示這樣類似的應用場景時,可以通過隊列組的方式并發執行任務,提高效率,使用方式如圖

多線程之NSThread、NSOperation及GCD

     (7)解決線程同步的問題除了使用串行隊列外,還可以使用信号量來解決,詳細參考Concurrency Programming Guide,另外需要注意的是以下兩個使用方式會産生問題

      一個是在主線程以dispatch_sync同步方式執行任務會死鎖

多線程之NSThread、NSOperation及GCD

    另一個是在并行隊列中以dispatch_sync同步方式執行任務,會失去并發的意義,最終所有任務都還是在主線程中一個一個執行

多線程之NSThread、NSOperation及GCD

    4.總結

     一般情況用NSOperation和GCD可以滿足應用需求,GCD方式使用起來已經足夠簡潔,而NSOperation使用起來則更加靈活友善,可以監聽任務執行狀态,取消任務,設定任務最大并發數量等等。