這篇主要總結下iOS開發中多線程的使用,多線程開發通常使用NSThread、NSOperation及GCD三種方式,經常使用GCD及NSOperation。多線程
建立線程主要有如下三種方式併發
須要注意的是對於多個線程可能同時訪問一個對象的時候,使用「@synchronized」來解決這類線程同步問題。異步
在子線程中通知主線程一般使用如下兩種辦法:async
NSOperation有三種使用方式,分別是NSInvocationOperation、NSBlockOperation以及自定義NSOperation操做,並可對NSOperation設置依賴關係,進而肯定任務執行的前後順序,還能夠對任務的狀態進行監控甚至控制,以及設置線程最大併發數量等等。ide
(1)NSInvocationOperationpost
首先是NSInvocationOperation方式建立線程如圖所示,須要注意的是這種方式建立的操做只有加入到隊列去執行纔是異步操做,不然仍是在主線程同步執行ui
加入到隊列自動執行時,會新建線程異步執行spa
(2)NSBlockOperation線程
第二種則是使用NSBlockOperation,一樣須要注意的是當操做的任務數只有一個時,任務會在當前線程同步執行
當任務數大於1的時候,會開啓新線程並異步執行
當把NSBlockOperation定義的操做加入到隊列中時,會以異步併發的方式去執行這些任務
(3)繼承NSOperation,自定義Operation
這種方法較爲靈活,經過繼承NSOperation並重寫相關方法實現,例如SDWebImage就用到了這種方式。
(4)設置依賴
若是任務之間有前後順序依賴,能夠對他們設置依賴關係解決這個問題,如圖所示,operation1依賴operation2,而operation2又依賴於operation3,因而執行順序爲operation三、operation二、operation1
(5)設置任務最大併發數
能夠經過設置maxConcurrentOperationCount限定任務併發數量,避免併發操做消耗太多資源
(6)任務狀態的監控以及設置
能夠獲取到任務的執行狀態,是否執行中仍是取消了或者完成了等等
須要注意的是,發送取消任務的消息,任務並不必定就真的取消,由於加入到隊列之後,任務的執行都是由系統來管理了,取消成功的前提是任務尚未開始執行,即便該任務成功取消了,也仍是會被系統認定爲任務已經完成finished,因此若是有其餘任務依賴於已經被取消的任務,須要用「isCancelled」進行判斷,尤爲是任務完成回調事件裏作一些操做的話,可能說的有點繞,詳細見下圖:
若是不進行判斷,即便operation3已經取消了,因爲系統認爲取消的任務也算finished,因此operation3的任務完成回調事件仍然觸發
更詳細的能夠參考Concurrency Programming Guide中這部分的內容
固然,還能夠直接對整個列進行管理,包括掛起或恢復隊列中全部任務,取消隊列裏全部任務等等
GCD的使用主要有如下幾種方式:
(1)在主線程中添加任務,dispatch_async異步方式執行,常見使用場景是進入之後,異步加載相關圖片信息
(2)GCD中解決線程同步的問題可使用串行隊列,串行隊列裏任務會按照添加順序依次執行,須要注意的是以distpatch_sync同步方式執行任務,全部任務都是在主線程進行的
(3)在串行隊列中以dispatch_async異步方式執行任務,則系統開啓一個新線程執行任務
(4)在併發隊列中,以dispatch_async異步方式執行任務,則系統會根據任務數量創建必定數量的線程來執行任務,注意這裏用的是全局併發隊列。
(5)GCD方式執行延時任務
上圖爲回到主線程執行延時任務,下圖爲開啓新的線程執行延時任務
(6)隊列組
當須要同時執行多個任務,例如同時下載多張圖片,並對圖片進行處理顯示這樣相似的應用場景時,能夠經過隊列組的方式併發執行任務,提升效率,使用方式如圖
(7)解決線程同步的問題除了使用串行隊列外,還可使用信號量來解決,詳細參考Concurrency Programming Guide,另外須要注意的是如下兩個使用方式會產生問題
一個是在主線程以dispatch_sync同步方式執行任務會死鎖
另外一個是在並行隊列中以dispatch_sync同步方式執行任務,會失去併發的意義,最終全部任務都仍是在主線程中一個一個執行
通常狀況用NSOperation和GCD能夠知足應用需求,GCD方式使用起來已經足夠簡潔,而NSOperation使用起來則更加靈活方便,能夠監放任務執行狀態,取消任務,設置任務最大併發數量等等。