iOS程序在啟動時會創(chuàng)建一個主線程,而在一個線程只能執(zhí)行一件事情屈尼,如果在主線程執(zhí)行某些耗時操作册着,例如加載網(wǎng)絡(luò)圖片,下載資源文件等會阻塞主線程(導(dǎo)致界面卡死脾歧,無法交互)甲捏,所以就需要使用多線程技術(shù)來避免這類情況。iOS中有三種多線程技術(shù) NSThread鞭执,NSOperation司顿,GCD,這三種技術(shù)是隨著IOS發(fā)展引入的兄纺,抽象層次由低到高免猾,使用也越來越簡單。本文將介紹一些多線程使用要點囤热,及NSThread常用方法以和各自的優(yōu)缺點。
環(huán)境信息:
Mac OS X 10.10.1
Xcode 6.1.1
iOS 8.1
正文:
一获三、多線程使用要點:
1)多線程使用并不是無節(jié)制的旁蔼,iOS主線程的堆棧大小是1M左右锨苏,從第二個線程開始都是512KB(蘋果API傳送門)
2)只有主線程可以修改UI(顯示圖片,更改textView文字等)棺聊,因為其余線程是獨立于Cocoa Touch的伞租,雖然有時在異步線程中可以實現(xiàn)更改界面,但是強烈不建議這么做
3)多線程并不能提高程序運行效率限佩,而是通過并發(fā)任務(wù)提高資源使用率來提高系統(tǒng)的整體性能
就單核而言葵诈,兩個線程可以解決線程阻塞問題,但執(zhí)行效率比起一個線程執(zhí)行是差不多的祟同,并且在創(chuàng)建一個新線程的時候會消耗一定內(nèi)存和CPU時間作喘。多線程只是充分發(fā)揮系統(tǒng)多核處理器的優(yōu)勢,并發(fā)執(zhí)行任務(wù)以提高效率晕城。但是在哪個CPU上執(zhí)行任務(wù)都是由系統(tǒng)調(diào)度的泞坦,我們不必太糾結(jié)系統(tǒng)有幾個CPU,只要關(guān)心線程的使用以及線程之間的關(guān)心就可以了砖顷。
4)盡量不要用多個線程去搶奪共享資源贰锁,如果確實有必要這樣做,需要注意線程安全
二滤蝠、NSThread
1)概述:
NSThread 是一個輕量級的多線程技術(shù)豌熄,每一個對象代表一個線程。
優(yōu)點:量級輕物咳,使用簡單
缺點:不能控制線程執(zhí)行順序锣险,不能控制線程并發(fā)數(shù),需要自己管理線程生命周期
2)開啟一個異步線程
// 1.類方法所森,直接新建線程調(diào)用某個耗時操作囱持,新建線程后直接自動啟動該線程
[NSThread detachNewThreadSelector:@selector(threadLoadImage:) toTarget:self withObject:imageView];
// 2.成員方法,新建線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadLoadImage:) object:imageView];
// 需要調(diào)用start方法來手動啟動線程
[thread start];
// 3.使用NSObject的類目方法焕济,performSelectorInBackground 會新建一個后臺線程纷妆,并在該線程中執(zhí)行調(diào)用的方法
[self performSelectorInBackground:@selector(threadLoadImage) withObject:imageView];
以上三種方法效果一樣,都是開啟一個異步線程晴弃,并在線程中執(zhí)行threadLoadImage:方法掩幢,只是使用是有細(xì)微差別
3)在主線程上執(zhí)行任務(wù)(界面更新等操作)
// 更新UI的操作需要在主線程操作
// 因為performSelectorOnMainThread:是NSObject的擴展方法,所以任何對象都可以調(diào)用此方法
[imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
4)查看當(dāng)前運行的線程
// 該方法可以在三種線程技術(shù)中任意調(diào)用上鞠,num代表當(dāng)前的線程號际邻,主線程的線程號一定是1
NSLog(@“當(dāng)前運行的線程 %@", [NSThread currentThread]);
5)內(nèi)存管理
- (void)threadLoadImage:(UIImageView *)imageView {
// 線程方法一定要加autoreleasepool
@autoreleasepool {
// 執(zhí)行你需要的耗時操作
}
}
6)線程休眠
// 指定休眠到多久日期
+ (void)sleepUntilDate:(NSDate *)date;
// 指定休眠的毫秒數(shù)
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
7)NSThread的一些屬性介紹
NSThread的大多屬性都漸漸的被廢棄了,所以在此只作為了解芍阎,不建議在開發(fā)中使用
// 線程的優(yōu)先級世曾,值在0-1之間,默認(rèn)為0.5谴咸,1為最高優(yōu)先級轮听,但是調(diào)用是由系統(tǒng)決定的骗露,所以指定優(yōu)先級有時比一定那么準(zhǔn)確。
@property double threadPriority NS_AVAILABLE(10_6, 4_0); // To be deprecated; use qualityOfService below
// 代替threadPriority屬性來指定線程的優(yōu)先級
@property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0); // read-only after the thread is started
// 線程的名稱
@property (copy) NSString *name NS_AVAILABLE(10_5, 2_0);
// 修改線程堆棧大小血巍, 子線程最小的堆大小為16KB萧锉,堆的大小必須是4KB的倍數(shù)
@property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);
// 是否是主線程
@property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);