iOS多線程

iOS多線程基礎(chǔ)

在iOS中,多線程的概念應(yīng)該算是比好理解的了.并沒有想象中那么難搞.簡單的概念像線程/進(jìn)程這些概念就不說了.

多線程其實真對單核的CPU來設(shè)計的.CPU同一時間只能執(zhí)行一條線程.而多線程就是讓CPU快速的在多個線程之間進(jìn)行調(diào)度

多線程優(yōu)點:

能夠適當(dāng)?shù)奶岣叱绦虻膱?zhí)行效率

能夠適當(dāng)提高資源利用率

缺點:

開啟線程需要一定的內(nèi)存空間,默認(rèn)的一條線程占用棧區(qū)內(nèi)存512KB

線程過多會導(dǎo)致CPU在線程上調(diào)度上的開銷比較大

程序設(shè)計比較復(fù)雜,比如線程間的通信/多線程的數(shù)據(jù)共享

iOS應(yīng)用程序中都是一個主線程,也成為UI線程

那么主線程的作用就是用來更新UI,顯示/刷新UI界面

處理UI時間: 比如點擊/滾動/拖拽/手勢

注意:不能將耗時操作放在主線程,這樣會給用戶一種卡的"體驗"


說下串行,并行,其實很簡單就像你用瀏覽器下載和用迅雷下載,瀏覽器下載一般都是一個接一個的去下載.而迅雷就會同時去下載你所需要的所有東西.

簡單入門級的多線程演示:

touchBegin{

[self ?performselector:@selector(nsoperation) ?withObject:nil ]

}

- (void) nsoperation {

for (int i = 0 , i < 50000 , i++){

nslog(" %d ?%d",i, [NSTread currentThread]);

? ?}

}

iOS多線程技術(shù)--pthread

pthread是一套C語言的多線程API 使用難度比較大 需要程序員手動管理線程的生命周期 ?能夠跨平臺/可移植 ?能夠在UNIX/LINX/Windows 下運行 ?

但是使用起來比較困難,參數(shù)比較難懂 可參照 http://www.baidu.baike.com

iOS多線程--NSThread

是一套OC框架 ?使用更加面向?qū)ο?簡單易用,可直接操作線程對象 ? 偶爾使用

需要程序員手動管理線程的聲明周期 ?

一般用來查看當(dāng)前線程是否是主線程:

=1 當(dāng)前線程是主線程,!=1 當(dāng)前線程是在子線程

iOS多線程--GCD

旨在代替NSThread多線程技術(shù),充分利用設(shè)備的多核

也是一套基于C語言的API ?不需要程序員手動管理線程的聲明周期 ? 經(jīng)常使用

iOS多線程--NSOperation

是一套OC的API,是對GCD的封裝 使用更加面向?qū)ο?? 不需要程序員手動管理線程的聲明周期

比GCD多一些更加簡單實用的功能 ?也是經(jīng)常使用 ?特別是在iOS4以后


iOS多線程中的鎖

互斥鎖:

@synchronized ?是為了保證其中代碼只有一天線程來執(zhí)行

所以@synchronized的范圍是越小效率才高

@synchronized()其中的參數(shù) ?就是能夠加鎖的任意ocject對象

局部變量,是每一條線程單獨擁有的,所以無法加鎖 ? 鎖一定要是所有線程共享的對象

一般使用self ? (全局的也是可以的)

自旋鎖:

自旋鎖存在于原子屬性的內(nèi)部

自旋鎖的特點就是當(dāng)發(fā)現(xiàn)有其他線程正在執(zhí)行鎖定的代碼,該線程會用死循環(huán)的方式去等待鎖定代碼執(zhí)行完畢

atomic(原子屬性): 默認(rèn)是線程安全的 ? ?當(dāng)多個線程寫入屬性時,保證同一時間只有一條線程能夠執(zhí)行寫入操作


線程間的通訊

在NSThread中線程間的通訊

方法: performSelectorOnMainThread: with object: waitUnitDone:

三個參數(shù): 方法選擇器,將該方法放到主線程執(zhí)行

? ? ? ? ? ? ? 傳遞給方法的參數(shù)

? ? ? ? ? ? ? ?是否等待被調(diào)用方法執(zhí)行完成, 有可能也會等待調(diào)用方法執(zhí)行完成! 幾率極小!


NSThread的三種線程創(chuàng)建方法:

1. NSThread * thread = [[NSThread alloc]initWithTarget: selector: object:] ? 創(chuàng)建初始化一條線程

?啟動線程 ? ?[thread start]

2. [NSThread detachNewThreadSelector: toTarget: withObject:] ?會立即執(zhí)行selector方法

就是會分離一個子線程取執(zhí)行selector方法

3.[self performSelectorInbackground: withObject: ]

這是NSObject的一個分類方法,所有NSObject都可以使用此方法在其他線程執(zhí)行方法,一旦指定,就會立即在后臺線程執(zhí)行方法 ? 使用比較靈活

介紹下NSThread中的幾個重要屬性:

name: 一般在比較復(fù)雜的商業(yè)應(yīng)用中會設(shè)置線程的名字,因為可以快速找出崩潰線程

isMainThread: 這個是用來檢測是否是主線程的屬性

threadPriority: 這個屬性是用來設(shè)置線程的優(yōu)先級(線程的優(yōu)先級是 用一個浮點數(shù)來表示: 0~1.0 , 默認(rèn)線程的優(yōu)先級是0.5) 注意: 設(shè)置線程的優(yōu)先級高,只是CPU會優(yōu)先調(diào)用該線程,調(diào)用該線程的可能性會高,并不是會將該線程執(zhí)行完后再去執(zhí)行別的線程 .

線程的狀態(tài)屬性:

isExecuting: 只讀屬性,線程是否正在運行

isFinished: 只讀屬性,線城是否完成

isCancelled: 只讀屬性,線程是否被取消


GCD--Grand Central Dispatch

是蘋果公司為 多核并行運算提出的 解決方案

GCD是輕量級的多線程技術(shù)

系統(tǒng)會自動管理線程的生命周期

GCD中2個核心概念:

任務(wù): 同步/異步

隊列: 串行/并發(fā)

程序員只需做兩件事: 1. 定制任務(wù),確定需要做的事情

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2. 將任務(wù)添加到隊列中( GCD會自動將任務(wù)從隊列中取出,放到對應(yīng)的線程, 任務(wù)的取出是遵循FIFO原則的:先進(jìn)先出,后進(jìn)后出)

調(diào)度任務(wù),執(zhí)行任務(wù)的方法: 同步/異步

同步: 一個任務(wù)沒有執(zhí)行完,就不會執(zhí)行下一個任務(wù)

異步: 不用等待當(dāng)前執(zhí)行任務(wù)完成,就可以執(zhí)行下一個任務(wù)

任務(wù)隊列組合:

1.串行隊列,同步任務(wù)

不會開啟線程,順序執(zhí)行任務(wù)

2.串行隊列,異步任務(wù)

會開啟一條線程,順序執(zhí)行任務(wù)

3.并發(fā)隊列,異步任務(wù)

會開啟多條線程,每條線程都會執(zhí)行任務(wù),所以不會順序

4.并發(fā)隊列,同步任務(wù)

不會開線程,,順序執(zhí)行

小結(jié): - 開不開線程,取決于任務(wù)是同步還是異步,同步不開,異步開

? ? ? ?- 開幾條線程,取決于隊列,串行開一條,并發(fā)開多條(異步任務(wù))

主隊列特點: 主隊列不是主線程

主線程上有任務(wù),主隊列不會調(diào)度隊列中的任務(wù)

主隊列異步任務(wù) : 等待主線程上的任務(wù)執(zhí)行完畢會執(zhí)行主隊列中的任務(wù)

主隊列同步任務(wù) : 等待主線程上的任務(wù)執(zhí)行完畢,同步任務(wù):當(dāng)前任務(wù)不執(zhí)行完畢,不會執(zhí)行下一條任務(wù)

所以會造成互相等待,死鎖!!!

同步任務(wù)的特點:

- 可以在隊列調(diào)度多個異步任務(wù)之前,指定一個同步任務(wù),讓所有異步任務(wù)等待同步任務(wù)執(zhí)行完畢,這就是依賴關(guān)系

全局隊列:(其實就是并發(fā)隊列<感覺是根據(jù)任務(wù)的同步/異步來確定的>)

就是給程序員使用的,方便程序員使用的

全局隊列和并發(fā)隊列的區(qū)別:

1>名稱(隊列后邊的參數(shù)<是個字符串其實就是隊列的名稱>),并發(fā)隊列有名稱,適合商業(yè)級軟件跟蹤錯誤報告

2>release , 在MRC開發(fā)時,并發(fā)隊列需要使用 dispatch_release(q);

目前絕大多數(shù)的軟件都會使用全局隊列. 比如比較優(yōu)秀的第三方框架會使用自定義的并發(fā)隊列!

全局隊列和串行隊列的選擇

全局隊列: ? 并發(fā),能夠調(diào)度多個線程,執(zhí)行效率高

? ? ? ? ? ? ? ?- 比較費電

串行隊列: ? 一個接一個,只能夠開啟一條線程,執(zhí)行效率比較低

? ? ? ? ? ? ? ?- 省電,省錢,省流量

所以選擇是根據(jù)用戶連網(wǎng)狀態(tài)來選擇:

- WIFI,可以多開線程, 6條

- 3G/4G,盡量少開線程,2~3條

延時操作:

dispatch_after(dispatch_time,(int64_t)(delayInSeconds * NSEC_PER_SEC)),

? ? ? ? ? ?dispatch_get_main_queue(),^{

});

一次性操作: ? 蘋果提供了一個一次性執(zhí)行的機(jī)制,不僅能夠保證只被執(zhí)行一次,而且是"線程安全"的

dispatch_once()

使用互斥鎖也可以,但是效率低


調(diào)度組:

dispatch_group_t

可以將多個任務(wù)放在同一個調(diào)度組中,同時監(jiān)聽這多個任務(wù)的下載,最后用dispatch_group_notify來通知

其實就是用一個調(diào)度組,可以監(jiān)聽全局隊列調(diào)度的任務(wù),執(zhí)行完畢后,在主隊列執(zhí)行最終處理

dispatch_group_notify本身是異步的,這個還可以用另一種方法還實現(xiàn)是:dispatch_group_wait()其中第二個參數(shù)就是等待時間,一般寫DISPATCH_TIME_FOREVER

第二種使用方法,經(jīng)常出現(xiàn)在三方框架中:AFN

dispatch_group_enter() ? ? ?進(jìn)入群組

dispatch_group_leave() ? ? ? 退出群組

這兩個方法必須成對出現(xiàn)



NSOperation

核心概念就是 將"操作"添加到"隊列"

NSOperation是一個抽象類,不能直接使用!

它是對GCD的面向?qū)ο蟮牡姆庋b

目的:定義子類共有的屬性和方法

子類: - NSInvocationOperation

? ? ? ?- NSBlockOperation

NSInvocationOperation:

只需要創(chuàng)建隊列,執(zhí)行start方法,就可以使用.

本質(zhì)上就是GCD中的并發(fā)隊列, 異步任務(wù)的執(zhí)行


NSBlockOperation:

可以直接來一個全局的隊列屬性,懶加載之后,可以對所有的NSOperation的子類,添加到隊列!

回主線程,直接[NSOperationQueue mainQueue]addOperationWithBlock:^ 就可以回主線程更新UI了非常簡單好用

最大并發(fā)操作數(shù):

從iOS8開始,無論是GCD還是NSOperation,都會開啟很多線程,在iOS7以前GCD通常只會開啟5~6條線程

線程數(shù)的增加說明了:

1 >底層的線程池變大了,能夠拿到的線程資源更多了!

2 >對控制同時并發(fā)的線程數(shù),要求更高了.

暫停/繼續(xù)/取消全部操作:

暫停/繼續(xù): ?NSOperation中的屬性isSuspended 是否掛起

可以對isSuspended判斷,判斷隊列是否掛起,來做任務(wù)的暫?;蛘呃^續(xù).

1.在設(shè)置隊列的掛起屬性(isSuspended)時,并不會判斷隊列中是否有操作

所以如果不希望用戶有困惑,可以提前做判斷,就是對隊列的operationCount屬性進(jìn)行判斷

2.在暫停的時候,隊列中的操作數(shù)是包括正在執(zhí)行的操作,再次繼續(xù)的時候,如果之前正在執(zhí)行的操作已經(jīng)完成,那么隊列中的操作數(shù)就只有沒有調(diào)度的操作

取消所有的操作:

通過設(shè)置隊列的cancelAllOperations屬性,可以取消隊列的所有操作

注意: 這個取消屬性,也是不會取消正在執(zhí)行的操作

依賴關(guān)系:

NSOperation提供了依賴關(guān)系

NSOperation的所有操作都是異步的,但是為了建立操作之間的依賴關(guān)系,所以提供了dependency的功能

GCD中可以通過同步任務(wù)來實現(xiàn),也可以通過串行隊列來實現(xiàn)

先設(shè)置以來關(guān)系: op2 addDenpendency: op1 ? 即 ?任務(wù)2依賴任務(wù)1,任務(wù)2會等任務(wù)1完成

將所有操作都加入到隊列中 addOperations:@[op1,op2,op3] ?waitUntilFinished:

withUntilFinished這個參數(shù)類似于GCD中的dispatch_group_wait(g , DISPATCH_TIME_FOREVER) ?是否等待所有操作完成

但是注意: ?不要指定循環(huán)依賴,雖然不會死鎖,但是隊列會不工作!!!以前的Xcode版本會死鎖.

指定依賴關(guān)系是可以跨隊列進(jìn)行的. ?將op1,op2添加到隊列上,將op3添加到主隊列上,一樣按照指定的依賴關(guān)系執(zhí)行.


NSOperation & GCD的對比

GCD ?iOS4.0之后推出的針對多核處理器并做了優(yōu)化的并發(fā)技術(shù),是C語言的

- 將"任務(wù)"添加到"隊列(串行/并發(fā)/全局/主隊列)",并且指定執(zhí)行任務(wù)的函數(shù)(同步/異步)

- 線程間的通訊 ?dispatch_get_main_queue()

- 提供了一些NSOperation不具備的功能

? ? ? ?- 一次性執(zhí)行

? ? ? ?- 延遲操作

? ? ? ?- 在NSOperation中也可實現(xiàn),相對來說比較麻煩

NSOperation是在iOS2.0之后推出的,蘋果推出GCD之后,對NSOperation底層重寫了一遍

- 將"操作"(異步執(zhí)行的任務(wù))添加到隊列(并發(fā)隊列),就會立即異步執(zhí)行

- 線程間的通訊 ?mainQueue

- 提供了一些GCD實現(xiàn)比較困難的功能

? ? ? ? ?- 最大線程并發(fā)數(shù)

? ? ? ? ?- 隊列的暫停/繼續(xù)

? ? ? ? ?- 取消所有操作

? ? ? ? ?- 指定操作之間的依賴關(guān)系 (GCD可以用同步任務(wù)來實現(xiàn))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 多線程 在iOS開發(fā)中為提高程序的運行效率會將比較耗時的操作放在子線程中執(zhí)行,iOS系統(tǒng)進(jìn)程默認(rèn)啟動一個主線程,用...
    郭豪豪閱讀 2,731評論 0 4
  • 歡迎大家指出文章中需要改正或者需要補(bǔ)充的地方,我會及時更新,非常感謝。 一. 多線程基礎(chǔ) 1. 進(jìn)程 進(jìn)程是指在系...
    xx_cc閱讀 7,398評論 11 70
  • .一.進(jìn)程 進(jìn)程:是指在系統(tǒng)中正在運行的一個應(yīng)用程序,每個進(jìn)程之間是獨立的,每個進(jìn)程均運行在其專用且受保護(hù)的內(nèi)存空...
    IIronMan閱讀 4,611評論 1 33
  • 我們身邊時時、處處有橋,從構(gòu)圖的角度,橋怎么拍? 下面構(gòu)圖君以身邊的福元橋為例,介紹拍橋的10種構(gòu)圖技法! 1、遠(yuǎn)...
    龍飛攝影閱讀 2,867評論 0 3
  • 我曾夢幻在數(shù)萬年里 人都像萬里長城無堅不摧而所向無敵 信仰精忠報國的理念 擁有發(fā)自內(nèi)心的情感 卸掉面具的真實自己 ...
    上官南929閱讀 162評論 0 2

友情鏈接更多精彩內(nèi)容