在iOS中每個進程啟動后都會建立一個主線程(UI線程),這個線程是其他線程的父線程埃疫。由于在iOS中除了主線程帚湘,其他子線程是獨立于Cocoa Touch的哮针,所以只有主線程可以更新UI界面(新版iOS中锤窑,使用其他線程更新UI可能也能成功璧针,但是不推薦)。iOS中多線程使用并不復(fù)雜渊啰,關(guān)鍵是如何控制好各個線程的執(zhí)行順序探橱、處理好資源競爭問題。常用的多線程開發(fā)有三種方式:
1.NSThread
2.NSOperation
3.GCD
三種方式是隨著iOS的發(fā)展逐漸引入的绘证,所以相比而言后者比前者更加簡單易用隧膏,并且GCD也是目前蘋果官方比較推薦的方式(它充分利用了多核處理器的運算性能)。
GCD
Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的解決方法迈窟。在iOS4.0開始之后才能使用私植。GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術(shù)的很高效和強大的技術(shù)〖烧ぃ現(xiàn)在的iOS系統(tǒng)都升級到7了车酣,所以不用擔(dān)心該技術(shù)不能使用。
(一)NSThread的使用
優(yōu)點:NSThread 比其他兩個輕量級
缺點:需要自己管理線程的生命周期索绪,線程同步湖员。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷。
NSThread 有兩種直接創(chuàng)建方式:第一個是實例方法瑞驱,第二個是類方法娘摔。
第一種方式會直接創(chuàng)建線程并且開始運行線程;
第二種方式是先創(chuàng)建線程對象唤反,然后再運行線程操作凳寺,在運行線程操作前可以設(shè)置線程的優(yōu)先級等線程信息。
其他同步
我們可以使用指令 @synchronized 來簡化 NSLock的使用彤侍,這樣我們就不必顯示編寫創(chuàng)建NSLock,加鎖并解鎖相關(guān)代碼肠缨。還有其他的一些鎖對象,比如:循環(huán)鎖NSRecursiveLock盏阶,條件鎖NSConditionLock晒奕,分布式鎖NSDistributedLock等等,可以自己看官方文檔學(xué)習(xí)。
(二)Cocoa NSOperation的使用
Cocoa NSOperation
優(yōu)點:不需要關(guān)心線程管理脑慧,數(shù)據(jù)同步的事情魄眉,可以把精力放在自己需要執(zhí)行的操作上。
Cocoa operation 相關(guān)的類是 NSOperation 闷袒,NSOperationQueue坑律。
NSOperation是個抽象類,使用 NSOperation的方式有兩種囊骤,一種是用定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation脾歇。另一種是繼承NSOperation。
如何控制線程池中的線程數(shù)淘捡?
隊列里可以加入很多個NSOperation, 可以把NSOperationQueue看作一個線程池藕各,可往線程池中添加操作(NSOperation)到隊列中。線程池中的線程可看作消費者焦除,從隊列中取走操作激况,并執(zhí)行它。線程池中的線程數(shù)膘魄,也就是并發(fā)操作數(shù)乌逐。默認情況下是-1,-1表示沒有限制创葡,這樣會同時運行隊列中的全部的操作浙踢。
(三)GCD的介紹和使用
介紹:
Grand Central Dispatch 簡稱(GCD)是蘋果公司開發(fā)的技術(shù),以優(yōu)化的應(yīng)用程序支持多核心處理器和其他的對稱多處理系統(tǒng)的系統(tǒng)灿渴。這建立在任務(wù)并行執(zhí)行的線程池模式的基礎(chǔ)上的洛波。它首次發(fā)布在Mac OS X 10.6 ,iOS 4及以上也可用骚露。
通過 GCD蹬挤,開發(fā)者不用再直接跟線程打交道了,只需要向隊列中添加代碼塊即可棘幸,GCD 在后端管理著一個線程池焰扳。GCD 不僅決定著你的代碼塊將在哪個線程被執(zhí)行,它還根據(jù)可用的系統(tǒng)資源對這些線程進行管理误续。這樣可以將開發(fā)者從線程管理的工作中解放出來吨悍,通過集中的管理線程,來緩解大量線程被創(chuàng)建的問題蹋嵌。
GCD 帶來的另一個重要改變是育瓜,作為開發(fā)者可以將工作考慮為一個隊列,而不是一堆線程欣尼,這種并行的抽象模型更容易掌握和使用爆雹。
首先停蕉,系統(tǒng)提供給你一個叫做 主隊列(main queue) 的特殊隊列。和其它串行隊列一樣钙态,這個隊列中的任務(wù)一次只能執(zhí)行一個慧起。然而,它能保證所有的任務(wù)都在主線程執(zhí)行册倒,而主線程是唯一可用于更新 UI 的線程蚓挤。這個隊列就是用于發(fā)生消息給 UIView 或發(fā)送通知的。
系統(tǒng)同時提供給你好幾個并發(fā)隊列驻子。它們叫做 全局調(diào)度隊列(Global Dispatch Queues) 灿意。目前的四個全局隊列有著不同的優(yōu)先級:background、low崇呵、default 以及 high缤剧。要知道,Apple 的 API 也會使用這些隊列域慷,所以你添加的任何任務(wù)都不會是這些隊列中唯一的任務(wù)荒辕。
最后,你也可以創(chuàng)建自己的串行隊列或并發(fā)隊列犹褒。這就是說抵窒,至少有五個隊列任你處置:主隊列、四個全局調(diào)度隊列叠骑,再加上任何你自己創(chuàng)建的隊列李皇。
GCD相比其他多線程有哪些優(yōu)點?
GCD 能通過推遲昂貴計算任務(wù)并在后臺運行它們來改善你的應(yīng)用的響應(yīng)性能宙枷。
GCD 提供一個易于使用的并發(fā)模型而不僅僅只是鎖和線程掉房,以幫助我們避開并發(fā)陷阱。
GCD 具有在常見模式(例如單例)上用更高性能的原語優(yōu)化你的代碼的潛在能力朦拖。
GCD 會自動利用更多的CPU內(nèi)核(比如雙核圃阳、四核)
GCD術(shù)語
串行(Serial):讓任務(wù)一個接著一個地執(zhí)行(一個任務(wù)執(zhí)行完畢后厌衔,再執(zhí)行下一個任務(wù))
并發(fā)(Concurrent):可以讓多個任務(wù)并發(fā)(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù))并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效璧帝。
同步(Synchronous):在當前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
異步(Asynchronous):在新的線程中執(zhí)行任務(wù)富寿,具備開啟新線程的能力
dispatch queue分為下面三種:
Serial:又稱為private dispatch queues睬隶,同時只執(zhí)行一個任務(wù)。Serial queue通常用于同步訪問特定的資源或數(shù)據(jù)页徐。當你創(chuàng)建多個Serial queue時苏潜,雖然它們各自是同步執(zhí)行的,但Serial queue與Serial queue之間是并發(fā)執(zhí)行的变勇。
Concurrent:又稱為global dispatch queue恤左,可以并發(fā)地執(zhí)行多個任務(wù)贴唇,但是執(zhí)行完成的順序是隨機的。
Main dispatch queue:它是全局可用的serial queue飞袋,它是在應(yīng)用程序主線程上執(zhí)行任務(wù)的戳气。
1、常用的方法dispatch_async
為了避免界面在處理耗時的操作時卡死巧鸭,比如讀取網(wǎng)絡(luò)數(shù)據(jù)瓶您,IO,數(shù)據(jù)庫讀寫等,我們會在另外一個線程中處理這些操作纲仍,然后通知主線程更新界面呀袱。用GCD實現(xiàn)這個流程的操作比前面介紹的NSThread? NSOperation的方法都要簡單。
系統(tǒng)給每一個應(yīng)用程序提供了三個concurrent dispatch queues郑叠。這三個并發(fā)調(diào)度隊列是全局的夜赵,它們只有優(yōu)先級的不同。因為是全局的乡革,我們不需要去創(chuàng)建油吭。我們只需要通過使用函數(shù)dispath_get_global_queue去得到隊列,如下:
dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
這里也用到了系統(tǒng)默認就有一個串行隊列main_queue:
dispatch_queue_t mainQ = dispatch_get_main_queue();
雖然dispatch queue是引用計數(shù)的對象署拟,但是以上兩個都是全局的隊列婉宰,不用retain或release。
2推穷、dispatch_group_async的使用
dispatch_group_async可以實現(xiàn)監(jiān)聽一組任務(wù)是否完成心包,完成后得到通知執(zhí)行其他的操作。這個方法很有用馒铃,比如你執(zhí)行三個下載任務(wù)娃殖,當三個任務(wù)都下載完成后你才通知dispatch_group_notify界面說完成的了议谷。dispatch_group_async是異步的方法炉爆,運行后可以看到打印結(jié)果罗捎。
3慈格、dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行,而且它后面的任務(wù)等它執(zhí)行完成之后才會執(zhí)行吮成。
4逼裆、dispatch_apply
執(zhí)行某個代碼片段N次郁稍。
總結(jié):
- NSThread是早期的多線程解決方案,實際上是把C語言的PThread線程管理代碼封裝成OC代碼胜宇。
- GCD是取代NSThread的多線程技術(shù),C語法+block财破。功能強大然评。
- NSOperationQueue是把GCD封裝為OC語法,額外比GCD增加了幾項新功能狈究。
* 最大線程并發(fā)數(shù)
* 取消隊列中的任務(wù)
* 暫停隊列中的任務(wù)
* 可以調(diào)整隊列中的任務(wù)執(zhí)行順序碗淌,通過優(yōu)先級
* 線程依賴
* NSOperationQueue支持KVO。 這就意味著你可以觀察任務(wù)的狀態(tài)屬性磅废。
但是NSOperationQueue的執(zhí)行效率沒有GCD高纳像,所以一半情況下,我們使用GCD來完成多線程操作拯勉。