你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS多線程開發筆記

iOS多線程開發筆記

編輯:IOS開發綜合

基本概念、術語:

進程(Precess):進程是操作系統管理和分配資源的最小單位,每個進程都有自己的內存空間、系統資源,至少有一個主線程和多個輔助線程。在iOS中,每個App運行的時候,都有對應的進程。 線程(Thread):線程則是操作系統具體的執行單元,代碼的執行是在線程來完成的。在iOS中,線程的底層實現是基於POSIX thread API的,也就是我們常說的pthread。 任務(Task):任務是我們抽象出來的需要執行的工作,一般指代一段代碼。 同步 vs 異步

同步是指函數的調用會阻塞當前的線程,必須等待函數返回才能繼續執行接下來的代碼。 異步函數的調用則不會阻塞當前線程,函數調用之後立刻返回,一般通過回調函數來處理函數的執行結果。 異步函數能夠有效的完成一些耗時的任務,而不必影響代碼的執行流,能夠提高代碼的處理效率。 串行 vs 並發

串行指的是在同一個時間只能有一個任務在執行。 並發指的是在同一個時間可以有多個任務一起執行。 並發一般用於多核編程,通過高效的利用多核的優勢,把不同的任務分配到各個執行單元來提高效率。 Dispatch Queue vs Operation Queue

GCD和NSOperation/NSOperationQueue是iOS上面來處理多線程開發的工具,對應的概念分別是Dispatch Queue和Operation Queue。

iOS並發編程模型

在其他的操作系統中,我們往往需要手動創建線程、管理線程的生命周期,在不需要的時候負責銷毀線程和線程使用的資源,更加痛苦的是需要使用線程鎖、信號量、代碼臨界區等手段完成線程的同步工作,這些操作往往容易出錯而且繁雜。 iOS通過抽象出隊列的概念,讓開發者更加關注於任務的安排和調度,而從線程的管理工作中解脫出來。在很多時候,iOS把一些繁雜且容易出錯的工作(ARC代替MRC)抽離到底層中,能夠讓開發者把注意力更多地放到真正的任務上,這也是iOS能夠吸引廣大開發者的原因之一吧。

NSThread vs GCD vs NSOperation,它們到底是什麼?

三種解決方案

NSThread:一個封裝pthread API的線程對象,需要進行線程創建、銷毀和處理線程同步,是最接近系統底層的解決方案。 GCD:蘋果基於C語言開發的,一個用於多核編程的解決方案,是一個輕量級的、以FIFO的順序來執行並發任務的庫。 NSOperation:建立在GCD的基礎上,面向對象的解決方案,比GCD更加靈活,也更加強大。

它們具體是什麼?

NSThread: Cocoa對於pthread API的封裝,提供了一套面向對象的接口,需要開發者自行管理線程的生命周期、處理線程同步。大多是的時候,我們是不需要直接使用這些底層的對象,而是使用GCD或者NSOperation等更加高級的接口。 關於Operation對象

NSOperation對象本身是一個抽象類,不能直接使用。要麼使用系統預定義的兩個子類NSInvocationOperation和NSBlockOperation或者定義它的子類。 NSInvocationOperation:可以使用object和selector來創建一個NSInvocationOperation,非常的方便和靈活。當代碼中已經有相關的處理邏輯方法時,建議直接使用NSInvocationOperation來進行替代。 NSBlockOperation:可以使用NSBlockOperation來並發的執行一個或者多個block,只有當所有的block都執行完畢,NSBlockOperation才算執行完成,有點像dispatch_group的概念。 所有的Operation都有下面的特性:

支持在 operation 之間建立依賴關系,只有當一個 operation 所依賴的所有 operation 都執行完成時,這個 operation 才能開始執行; 支持一個可選的 completion block ,這個 block 將會在 operation 的主任務執行完成時被調用,在任務被取消的時候也會執行; 支持通過 KVO 來觀察 operation 執行狀態的變化,Operation正是通過KVO通知來實現依賴運行,所以我們需要在自定義的子類中的處理好KVO的屬性; 支持設置執行的優先級,從而影響 operation 之間的相對執行順序; 支持取消操作,可以允許我們停止正在執行的 operation 。 GCD隊列:

以FIFO順序執行任務的隊列調度系統,先入隊列的任務一定先執行。 兩種類型的隊列:

串行隊列(Serial Queue):同一時間內只能有一個任務正在被執行。 並發隊列(Concurrent Queue):同一時間內可以有多個任務同時被執行。 iOS默認提供5個隊列:

主隊列(Main Queue):應用程序主線程應用的隊列,用於更新UI,屬於串行隊列。 四個全局隊列: 按照隊列優先級排序,分別是:High、Default、Low、Background。 這四個全局隊列是由系統提供的,在所有的App中共享,當然也包含了Apple的應用。 並發隊列中任務的執行順序: 由於隊列的並發數是有系統根據當前的資源動態管理的,我們不知道也不能夠設置隊列中任務執行的時機和所需時長。 只有當位於隊列前面的任務執行完畢、出隊列後,才會執行後面的任務,但是當前並發執行的任務數量我們不得而知。 自定義隊列:

我們可以自定義串行或者並發隊列來完成任務的執行和調度。

各自的優勢和劣勢

優勢:

NSThread:

能夠執行實時任務。其他兩者都是由系統管理的隊列,不能保證實時性。 GCD:

可以非常簡潔的完成簡單異步任務的調用,如在主線程更新UI,延遲執行。 只需要把任務分發到隊列之後,不需要管理任務的調度情況。 NSOperation:

給任務添加依賴 取消或者暫停一個正在執行的任務 有一個可選的completionBlock 可以通過KVO來查看任務的執行情況 可以給任務設置優先級,從而影響任務的執行順序 短板:

NSThread:需要進行線程的創建、銷毀,以及處理線程同步的問題,過於繁雜,而且容易出錯。 GCD:

對於任務的管理不夠:如不能取消任務、設置依賴和優先級等。 NSOperation:

相比於GCD,會增加系統的額外開銷。

多線程代碼中,需要注意哪些問題?

有了GCD來調度block,我們為什麼還需要NSBlockOperation?

現有代碼已經在使用OperationQueue,而我們不想使用Dispatch Queue的時候,NSBlockOperation提供了一個面向對象的封裝。 當我們需要dispatch queue不能提供的功能時,如KVO觀察Operation狀態變化、設置operation之間依賴等。 NSInvocationOperation的靈活性是什麼意思?

我們可以通過上下文來改變selector和object對象。 如何定義一個非並發的operation?

對於非並發的operation,我們只需要實現main方法和能夠正常響應取消事件。 其他復雜的工作如KVO通知、依賴設置等工作NSOperation類的start方法已經幫我們提供了默認實現。 簡單實現:

提供一個自定義的初始化方法 重寫main方法 如何實現一個並發的operation?

一般我們不需要實現並發的operation,當operation和operation queue一起使用的時候,Operation Queue會為非並發的operation創建單獨的線程。 默認情況下,operation是同步執行的,也就是我們直接使用start方法的時候,它是在調用者的線程中執行的。 Operation的isConcurrent屬性表明一個operation是否支持並發。 配置並發的Operation:只有當我們需要手動執行operation,並且希望支持並發執行,需要重寫下面的方法。

start:必須,配置任務執行的線程和其他資源,但是一定不能調用父類的實現。 main:可選,一般用來執行具體的任務,而start方法更多是用來配置初始環境,當然也可以用來執行具體的任務。 isExecuting和isFinished:必須,並發的Operation需要自己來配置環境,同時還需要向外界來傳遞狀態的變化,而isExecuting和isFinished這兩個狀態的變化需要使用KVO來通知外部。 isConcurrent:必須,用來標識一個Operation是否支持並發。 如何完成自定義operation的cancel操作?

在下面這幾個關鍵點的檢查isCancelled屬性

在真正開始執行operaiton之前 至少在一次循環之中需要檢查一次,如果單次循環耗時較長,則需要更加頻繁的檢查 在任何相對比較容易終止Operation的地方 需要注意的是雖然Operation支持取消操作,但是並不是立刻就可以被終止的,而是在下一個isCancelled的檢查點。 在我們自定義Operation子類的時候,即使operation是被cancel了,我們仍然需要設置isFinished方法為true,因為在設置operation依賴的時候,它們的operation就是通過KVO來觀察isFinished方法來判斷時候可以執行的,如果在cancel的時候,沒有設置isFinished方法,那麼其他的operation將永遠不會執行。 如何定制Operation對象的執行行為:

在Operation添加到Operation Queue之前,我們可以配置Operation的一些行為。 配置依賴關系

依賴關系是在Operation之間的,與是否在同一個Operation Queue沒有關系,也就是說,我們在位於不同的Operation Queue中的Operation之間設置依賴。 注意不要產生依賴循環。 在把operation添加到Operation Queue之前就需要配置好依賴,在添加後設置的依賴可能無效。 修改operation在隊列中的優先級

Operation在隊列中的執行順序取決於isReady狀態和隊列優先級。 isReady受它所依賴的operation狀態的影響,只有當依賴的所有operation都變為isFinished的時候,isReady狀態才為true。 queuePriority只能作用與相同隊列中的operation,並且隊列優先級只有當isReady為true的時候,才會決定operation的執行順序。 isReady為FALSE的時候,isReady為true的低隊列優先級的operation也會先執行。 一個串行的 operation queue 與一個串行的 dispatch queue是一樣的麼?

兩者都是在同一時間內只能有一個任務被執行,但是在任務的執行順序上是不同的:

dispatch queue 的執行順序一直是 FIFO 的 operation queue中的operation執行的順序取決於isReady和queuePriority狀態。 如何用GCD實現一個線程安全的單例?

ObjC Swift

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved