NSThread:
優(yōu)點:
NSThread 比其他兩個輕量級
缺點:
需要自己管理線程的生命周期,線程同步。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
NSThread 會在執(zhí)行完任務(wù)函數(shù)時被自動收回
創(chuàng)建了一個NSThread對象,就創(chuàng)建了一條線程。
創(chuàng)建:
//實例方法
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
- (instancetype)initWithBlock:(void (^)(void))block
//類方法:通過類名直接調(diào)用的方法
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
+ (void)detachNewThreadWithBlock:(void (^)(void))block
//1
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
detach方法直接創(chuàng)建并啟動一個線程去Selector,由于沒有返回值,如果需要獲取新創(chuàng)建的Thread,需要在執(zhí)行的Selector中調(diào)用-[NSThread currentThread]獲取
//2
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(doSomething:)
object:nil];
[myThread start];
第一種方式會直接創(chuàng)建線程并且開始運行線程,第二種方式是先創(chuàng)建線程對象,然后再執(zhí)行運行線程操作,
優(yōu)點: 可以拿到線程對象, 并設(shè)置相關(guān)屬性
缺點: 代碼量相對多一點, 需要手動啟動線程
在運行線程操作前可以設(shè)置線程的優(yōu)先級等線程信息 thread.threadPriority = 1;
還有 initWithBlock: 方法。
target和@selector的關(guān)系 : 執(zhí)行哪個對象上的哪個方法.
運行:
CPU負責(zé)調(diào)度"可調(diào)度線程池"中的處于"就緒狀態(tài)"的線程
線程執(zhí)行結(jié)束之前,狀態(tài)可能會在"就緒"和"運行"之間來回的切換
"就緒"和"運行"之間的狀態(tài)切換由CPU來完成,程序員無法干涉
線程間的通信:用NSObject的類方法
(在一個線程里去別的線程執(zhí)行)
在一個線程中執(zhí)行完畢特定任務(wù)后, 轉(zhuǎn)到另一個線程繼續(xù)執(zhí)行任務(wù)
下載圖片:
開啟一個子線程去加載圖片, 下載完畢之后再回到主線程顯示圖片, 這個就是線程之間的通信.
//不顯式創(chuàng)建線程的方法:創(chuàng)建完直接啟動
[self performSelectorInBackground:@selector(doSomething) withObject:nil];
//線程間通訊:
//在當(dāng)前線程上執(zhí)行操作
[self performSelector:@selector(run) withObject:nil];
//在指定線程上執(zhí)行操作
[self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];
//在主線程上執(zhí)行操作
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];
線程延時 阻塞線程
//主線程和子線程中均可執(zhí)行。是一種阻塞的執(zhí)行方式,建議放到子線程中,以免卡住界面,
[NSThread sleepForTimeInterval:3.0];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];
常用的方法:
- (NSThread *)currentThread; //獲得當(dāng)前線程 [NSThread currentThread]
- (void)sleepForTimeInterval:(NSTimeInterval)ti; //線程休眠、延時
sleepUntilDate:
- (void)sleepForTimeInterval:(NSTimeInterval)ti; //線程休眠、延時
//[NSThread sleepForTimeInterval:3.0];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];
- (NSThread *)mainThread; //獲得主線程,亦即UI線程
- (BOOL)isMainThread; + (BOOL)isMainThread; //當(dāng)前線程是否主線程
- (BOOL)isExecuting; //線程是否正在運行
- (BOOL)isFinished; //線程是否已結(jié)束
isCancelled
setName: //設(shè)置名字
setThreadPriority: //iOS 8以前 優(yōu)先級 (不是先執(zhí)行,確切是執(zhí)行概率)
setQualityOfService: //iOS 8以后 通過枚舉值設(shè)置優(yōu)先級
start
cancel //并不會馬上停止并退出線程,僅僅只作(線程是否需要退出)狀態(tài)記錄
[_myThread cancel];并沒有取消該線程,只是給該線程設(shè)置了一個標(biāo)志位,需要到具體任務(wù)里根據(jù)線程的.cancelled屬性判斷來取消。
exit //強制停止 不能重啟 不要在主線程調(diào)用 會使主線程退出.
threadPriority //線程的"優(yōu)先級"不是決定線程調(diào)用順序的,他是決定線程備CPU調(diào)用的頻率的
- (BOOL)isFinished; //線程是否已結(jié)束
線程同步: 線程安全
比如搶票,同一時間只有一個線程操作票數(shù)數(shù)據(jù)。需要用到加鎖
@synchronized(對象){ // 需要鎖定的代碼 }
NSThread有三個線程相關(guān)的通知
NSWillBecomeMultiThreadedNotification://由當(dāng)前線程派生出第一個其他線程時發(fā)送,一般一個線程只發(fā)送一次
NSDidBecomeSingleThreadedNotification://這個通知目前沒有實際意義,可以忽略
NSThreadWillExitNotification //線程退出之前發(fā)送這個通知
生命周期
只有當(dāng)需要執(zhí)行的任務(wù)全部執(zhí)行完畢之后才會被釋放掉.
線程啟動后,執(zhí)行@selector完畢后就馬上退出了,怎樣能讓線程一直運行呢(窗口一直開放,可以隨時指派其賣演唱會的門票的任務(wù)),答案就是給線程加上runLoop
參考:
http://www.itdecent.cn/p/cbaeea5368b1
http://www.itdecent.cn/p/0d4812426f72
http://www.itdecent.cn/p/cf47dccd6e27
http://www.cocoachina.com/ios/20160225/15421.html
https://blog.csdn.net/hbblzjy/article/details/51565590 (通知監(jiān)聽)