iOS-多線程:NSThread

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:
//[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)用的頻率的

線程同步: 線程安全

比如搶票,同一時間只有一個線程操作票數(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)聽)

最后編輯于
?著作權(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)容

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