(1)NSThread的基本使用
第一種創(chuàng)建線程的方式:alloc init.
特點:需要手動開啟線程,可以拿到線程對象進行詳細設(shè)置
創(chuàng)建線程
第一個參數(shù):目標對象
第二個參數(shù):選擇器,線程啟動要調(diào)用哪個方法
第三個參數(shù):前面方法要接收的參數(shù)(最多只能接收一個參數(shù),沒有則傳nil)
NSThread *thread = [[NSThread alloc]initWithTarget:selfselector:@selector(run:) object:@"wendingding"];
啟動線程
[thread start];
第二種創(chuàng)建線程的方式:分離出一條子線程
特點:自動啟動線程,無法對線程進行更詳細的設(shè)置
第一個參數(shù):線程啟動調(diào)用的方法
第二個參數(shù):目標對象
第三個參數(shù):傳遞給調(diào)用方法的參數(shù)
[NSThread detachNewThreadSelector:@selector(run:) toTarget:selfwithObject:@"我是分離出來的子線程”];
第三種創(chuàng)建線程的方式:后臺線程
特點:自動啟動線程,無法進行更詳細設(shè)置
[selfperformSelectorInBackground:@selector(run:) withObject:@"我是后臺線程"];
(2)設(shè)置線程的屬性
設(shè)置線程的屬性
設(shè)置線程的名稱
thread.name=@"線程A";
設(shè)置線程的優(yōu)先級,注意線程優(yōu)先級的取值范圍為0.0~1.0之間,1.0表示線程的優(yōu)先級最高,如果不設(shè)置該值,那么理想狀態(tài)下默認為0.5
thread.threadPriority = 1.0;
(3)線程的狀態(tài)(了解)
線程的各種狀態(tài):新建-就緒-運行-阻塞-死亡
常用的控制線程狀態(tài)的方法
[NSThread exit];退出當前線程
[NSThread sleepForTimeInterval:2.0];阻塞線程
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];阻塞線程
注意:線程死了不能復(fù)生
(4)線程安全
01前提:資源共享
1塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源
比如多個線程訪問同一個對象、同一個變量、同一個文件
當多個線程訪問同一塊資源時,很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全問題
02解決方案:加互斥鎖
互斥鎖的優(yōu)缺點
優(yōu)點:能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
缺點:需要消耗大量的CPU資源
互斥鎖的使用前提:多條線程搶奪同一塊資源
相關(guān)專業(yè)術(shù)語:線程同步
線程同步的意思是:多條線程在同一條線上執(zhí)行(按順序地執(zhí)行任務(wù))
互斥鎖,就是使用了線程同步技術(shù)
03相關(guān)代碼:@synchronized(self){}
注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的
04專業(yè)術(shù)語-線程同步
05原子和非原子屬性(是否對setter方法加鎖)
原子和非原子屬性
OC在定義屬性時有nonatomic和atomic兩種選擇
atomic:原子屬性,為setter方法加鎖(默認就是atomic)
nonatomic:非原子屬性,不會為setter方法加鎖
原子和非原子屬性的選擇
nonatomic和atomic對比
atomic:線程安全,需要消耗大量的資源
nonatomic:非線程安全,適合內(nèi)存小的移動設(shè)備
iOS開發(fā)的建議
所有屬性都聲明為nonatomic
盡量避免多線程搶奪同一塊資源
盡量將加鎖、資源搶奪的業(yè)務(wù)邏輯交給服務(wù)器端處理,減小移動客戶端的壓力
(5)線程間通信
-(void)touchesBegan:(nonnullNSSet *)touches withEvent:(nullableUIEvent *)event
{
[self download2];
開啟一條子線程來下載圖片
[NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:selfwithObject:nil];
}
-(void)downloadImage
{
1.確定要下載網(wǎng)絡(luò)圖片的url地址,一個url唯一對應(yīng)著網(wǎng)絡(luò)上的一個資源
NSURL *url = [NSURL URLWithString:@"http://p6.qhimg.com/t01d2954e2799c461ab.jpg"];
2.根據(jù)url地址下載圖片數(shù)據(jù)到本地(二進制數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfURL:url];
3.把下載到本地的二進制數(shù)據(jù)轉(zhuǎn)換成圖片
UIImage *image = [UIImage imageWithData:data];
4.回到主線程刷新UI
4.1第一種方式
[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];
4.2第二種方式
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
4.3第三種方式
[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
}
(6)如何計算代碼段的執(zhí)行時間
第一種方法
NSDate *start = [NSDate date];
2.根據(jù)url地址下載圖片數(shù)據(jù)到本地(二進制數(shù)據(jù))
NSData *data = [NSData dataWithContentsOfURL:url];
NSDate *end = [NSDate date];
NSLog(@"第二步操作花費的時間為%f",[end timeIntervalSinceDate:start]);
第二種方法
CFTimeInterval start = CFAbsoluteTimeGetCurrent();
NSData *data = [NSData dataWithContentsOfURL:url];
CFTimeInterval end = CFAbsoluteTimeGetCurrent();
NSLog(@"第二步操作花費的時間為%f",end - start);