這篇主要總結(jié)下iOS開發(fā)中多線程的使用,多線程開發(fā)一般使用NSThread、NSOperation及GCD三種方式,常用GCD及NSOperation。
創(chuàng)建線程主要有以下三種方式

需要注意的是對于多個線程可能同時訪問一個對象的時候,使用“@synchronized”來解決這類線程同步問題。
在子線程中通知主線程通常使用以下兩種辦法:
NSOperation有三種使用方式,分別是NSInvocationOperation、NSBlockOperation以及自定義NSOperation操作,并可對NSOperation設(shè)置依賴關(guān)系,進(jìn)而確定任務(wù)執(zhí)行的先后順序,還可以對任務(wù)的狀態(tài)進(jìn)行監(jiān)控甚至控制,以及設(shè)置線程最大并發(fā)數(shù)量等等。
(1)NSInvocationOperation
首先是NSInvocationOperation方式創(chuàng)建線程如圖所示,需要注意的是這種方式創(chuàng)建的操作只有加入到隊(duì)列去執(zhí)行才是異步操作,否則還是在主線程同步執(zhí)行


加入到隊(duì)列自動執(zhí)行時,會新建線程異步執(zhí)行


(2)NSBlockOperation
第二種則是使用NSBlockOperation,同樣需要注意的是當(dāng)操作的任務(wù)數(shù)只有一個時,任務(wù)會在當(dāng)前線程同步執(zhí)行

當(dāng)任務(wù)數(shù)大于1的時候,會開啟新線程并異步執(zhí)行

當(dāng)把NSBlockOperation定義的操作加入到隊(duì)列中時,會以異步并發(fā)的方式去執(zhí)行這些任務(wù)

(3)繼承NSOperation,自定義Operation
這種方法較為靈活,通過繼承NSOperation并重寫相關(guān)方法實(shí)現(xiàn),例如SDWebImage就用到了這種方式。
(4)設(shè)置依賴
如果任務(wù)之間有先后順序依賴,可以對他們設(shè)置依賴關(guān)系解決這個問題,如圖所示,operation1依賴operation2,而operation2又依賴于operation3,于是執(zhí)行順序?yàn)閛peration3、operation2、operation1

(5)設(shè)置任務(wù)最大并發(fā)數(shù)
可以通過設(shè)置maxConcurrentOperationCount限定任務(wù)并發(fā)數(shù)量,避免并發(fā)操作消耗太多資源

(6)任務(wù)狀態(tài)的監(jiān)控以及設(shè)置
可以獲取到任務(wù)的執(zhí)行狀態(tài),是否執(zhí)行中還是取消了或者完成了等等

需要注意的是,發(fā)送取消任務(wù)的消息,任務(wù)并不一定就真的取消,因?yàn)榧尤氲疥?duì)列以后,任務(wù)的執(zhí)行都是由系統(tǒng)來管理了,取消成功的前提是任務(wù)還沒有開始執(zhí)行,即使該任務(wù)成功取消了,也還是會被系統(tǒng)認(rèn)定為任務(wù)已經(jīng)完成finished,所以如果有其他任務(wù)依賴于已經(jīng)被取消的任務(wù),需要用“isCancelled”進(jìn)行判斷,尤其是任務(wù)完成回調(diào)事件里做一些操作的話,可能說的有點(diǎn)繞,詳細(xì)見下圖:

如果不進(jìn)行判斷,即使operation3已經(jīng)取消了,由于系統(tǒng)認(rèn)為取消的任務(wù)也算finished,所以operation3的任務(wù)完成回調(diào)事件仍然觸發(fā)

更詳細(xì)的可以參考Concurrency PRogramming Guide中這部分的內(nèi)容

當(dāng)然,還可以直接對整個列進(jìn)行管理,包括掛起或恢復(fù)隊(duì)列中所有任務(wù),取消隊(duì)列里所有任務(wù)等等

GCD的使用主要有以下幾種方式:
(1)在主線程中添加任務(wù),dispatch_async異步方式執(zhí)行,常見使用場景是進(jìn)入以后,異步加載相關(guān)圖片信息

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

(3)在串行隊(duì)列中以dispatch_async異步方式執(zhí)行任務(wù),則系統(tǒng)開啟一個新線程執(zhí)行任務(wù)
(4)在并發(fā)隊(duì)列中,以dispatch_async異步方式執(zhí)行任務(wù),則系統(tǒng)會根據(jù)任務(wù)數(shù)量建立一定數(shù)量的線程來執(zhí)行任務(wù),注意這里用的是全局并發(fā)隊(duì)列。

(5)GCD方式執(zhí)行延時任務(wù)

上圖為回到主線程執(zhí)行延時任務(wù),下圖為開啟新的線程執(zhí)行延時任務(wù)

(6)隊(duì)列組
當(dāng)需要同時執(zhí)行多個任務(wù),例如同時下載多張圖片,并對圖片進(jìn)行處理顯示這樣類似的應(yīng)用場景時,可以通過隊(duì)列組的方式并發(fā)執(zhí)行任務(wù),提高效率,使用方式如圖

(7)解決線程同步的問題除了使用串行隊(duì)列外,還可以使用信號量來解決,詳細(xì)參考Concurrency Programming Guide,另外需要注意的是以下兩個使用方式會產(chǎn)生問題
一個是在主線程以dispatch_sync同步方式執(zhí)行任務(wù)會死鎖

另一個是在并行隊(duì)列中以dispatch_sync同步方式執(zhí)行任務(wù),會失去并發(fā)的意義,最終所有任務(wù)都還是在主線程中一個一個執(zhí)行

一般情況用NSOperation和GCD可以滿足應(yīng)用需求,GCD方式使用起來已經(jīng)足夠簡潔,而NSOperation使用起來則更加靈活方便,可以監(jiān)聽任務(wù)執(zhí)行狀態(tài),取消任務(wù),設(shè)置任務(wù)最大并發(fā)數(shù)量等等。
新聞熱點(diǎn)
疑難解答
圖片精選