iOS多執行緒講解一之NSThread

weixin_33670713發表於2016-04-05

本文主要參考Apple官方文件,英文好的可以直接看官方文件

一個NSThread物件控制一個執行緒的執行。當你想有一個OC方法執行在它自己的執行緒中,你可以使用這個類。執行緒是特別有用,當您需要執行一個冗長的任務,但是不想讓它阻止執行應用程式的其餘部分。特別是,您可以使用執行緒來避免阻塞應用程式的主執行緒,處理使用者介面互動和與事件相關的方法。執行緒也可以用來將大量的工作分成幾個較小的工作,從而提高多核計算機的效能。
在OSXv10.5以前,唯一一個啟動執行緒的方法是使用detachNewThreadSelector:toTarget:withObject:,在OSX10.5及以後,你可以建立一個NSThread例項,然後呼叫start方法啟動它。
在OSXv10.5 ,該NSThread類支援用NSOperation的監測執行緒的執行狀態。您可以使用NSOperation取消執行緒的執行或確定執行緒是否仍在執行或已經完成了它的任務。取消一個執行緒需要來自你的執行緒程式碼的支援。
在 OSXv10.5 及以後,你可以子類化NSThread,並且重寫main方法來實現你的執行緒入口。如果你重新了main方法,你沒有必要再通過super去呼叫父類。

  • 初始化一個NSThread物件的方法:
-(instanceType)init;
NSThread *thread = [[NSThread alloc] init];

- (nullable instancetype)initWithTarget:(id)target
                               selector:(SEL)sel 
                                 object:(nullable id)arg;
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction:) object:nil];
  • 啟動執行緒的方法:
+ (void)detachNewThreadSelector:(SEL)selector 
                       toTarget:(id)target 
                     withObject:(nullable id)argument;

NOTE:aTarget 和 anArgument 在分離出來的執行緒的執行過程中被保留,然後釋放。一旦aTarget執行完aSelector方法,分離出來的執行緒就會退出(使用exit方法)。
如果執行緒是第一次被從應用中分離出來,這個方法就會往預設的通知中心傳送一個通知NSWillBecomeMultiThreadedNotification。

- (void)start;

NOTE:呼叫這個方法將產生一個新的執行緒、並且呼叫接收者的main方法。如果你使用target和selector初始化接收者,那麼main方法將會自動呼叫selector方法。
如果執行緒是第一次被從應用中分離出來,這個方法就會往預設的通知中心傳送一個通知NSWillBecomeMultiThreadedNotification。

- (void)main;

NOTE: 這個方法預設的實現是用target和selector方法初始化接收者,並且在特定的接收者裡面呼叫selector方法,如果你子類化NSThread類,你可以重寫main方法,並且實現它。如果你這樣做,你就沒有必要呼叫super。
你絕不能直接呼叫mian方法,你應該通過呼叫start方法啟動你的執行緒。

  • 暫停一個執行緒
//date:恢復執行緒的時間
+ (void)sleepUnitDate:(NSDate *)date;
//執行緒暫停的時長
+(void)sleepForTimeInterval:(NSTimeIntrval)ti;
- (void)exit;

NOTE:這個方法使用currentThread類方法訪問當前執行緒。在退出這個執行緒之前,這個方法往預設的通知中心傳送帶有執行緒退出內容的通知NSThreadWillExitNotification。 因為通知是被同步的傳送的,所以能保證通知NSThreadWillExitNotification的所有觀察者線上程退出之前能收到通知,因為執行緒不會清理在執行過程中申請的資源,所有應該避免使用這個方法。

- (void)cancel;

NOTE:改變接收者的取消狀態以表明執行緒將要退出。

  • 決定執行緒的執行狀態
//一個用於判斷執行緒是否正在執行的布林值(只讀)
@property(readonly, getter=isExecuting) BOOL executing 
//一個用於判斷執行緒是否執行完成的布林值(只讀)
@property(readonly, getter=isFinished) BOOL finished  
//一個用於判斷執行緒是否被取消的布林值(只讀)
@property(readonly, getter=isCancelled) BOOL cancelled  
說明:如果你的執行緒支援取消,那麼你需要定期的檢查執行緒的狀態,並且如果isCancelled為YES,就呼叫exit退出。
  • Main Thread
//判斷當前執行緒是否是主執行緒
- (BOOl)isMainThread;
//返回當前的主執行緒
+ (NSThread *)mainThread;
  • 查詢當前環境
//判斷當前應用是否是多執行緒應用
+ (BOOL)isMutiThreaded;

NOTE:在應用中,如果你使用方法detachNewThreadSelector:toTarget:withOb
ject:
start建立一個執行緒,那麼這個應用就是多執行緒應用,如果你使用non-CocoaAPI,例如POSIX或Multiprocessing Services APIs,那麼這個應用就不是多執行緒應用。

//返回表示當前正在執行的執行緒物件
+ (NSThread *)currentThread;
//返回包含呼叫堆疊返回地址的陣列。
+ (NSArray<NSNumber *> *)callStackReturnAddresses;

返回一個包含呼叫堆疊返回地址的陣列,每一個元素是一個包含NSUInteger值的NSNumber物件。

//返回包含堆疊呼叫符號的陣列
+(NSArray<NSSTring *> *)callStackSymbols;

NOTE:返回包含堆疊呼叫符號的陣列.每個元素是由backtrace_symbols函式確定格式的值的一個NSString物件。

  • 執行緒屬性
//返回執行緒物件的字典
@property(readonly, retain) NSMutableDictionary *threadDictionary;

NOTE:您可以使用返回的字典儲存特定執行緒的資料。執行緒字典線上程的任何操作期間不能夠被使用-它只是用來儲存一些你想要儲存的資料。例如:Foundation用它來儲存執行緒的預設NSConnection連線和NSAssertionHandler例項。你可以自定義你字典的keys。

//接收者的名字
@property(copy) NSString *name;
//接收器的堆疊大小,以位元組為單位
@property NSUInteger stackSize;

NOTE:該值必須以位元組為單位,並且是4KB的倍數。如果你要改變堆疊大小,你必須在你開始你的執行緒之前設定這個屬性。如果你線上程啟動之後在設定堆疊屬性,會改變屬性的大小(這是通過 stackSize方法反應的),但是不會影響預留執行緒的實際頁數。

  • 執行緒優先順序
//返回當前執行緒的優先順序
+(double)priority;

NOTE:returnValue:返回當前執行緒的優先順序,取值範圍是[0.0 1.0],1.0是最高優先順序。
在此範圍內的優先順序被對映到作業系統的優先順序值。 “典型”的執行緒優先順序可能是0.5 ,但由於優先順序由核心決定的,但不保證此值實際上將是什麼。

//設定執行緒的優先順序
+ (BOOL)setThreadPriority:(double) priority;
  • 通知(Notifications)
NSDidBecomeSingleThreadedNotification

NOTE:當一個執行緒收到exit命令時,線上程退出之前,它會傳送這個通知。收到這個通知的觀察者會線上程退出前執行退出方法。
通知物件是離開的NSThread物件。這個通知不包含userInfo字典資訊。

NSThreadWillExitNotification

NOTE:當有一個執行緒從當前執行緒中分離出去的時候傳送這個通知。NSThread類最多隻能傳送一次這個通知,在第一次使用 detachNewThreadSelector:toTarget:
withObject:
或者使用方法start的時候。後續這些方法的呼叫不會再次傳送該通知。這些觀察者在主執行緒中呼叫他們的通知方法,而不是在新執行緒中,觀察者的通知方法總是在執行新執行緒開始執行之前執行。
這個通知不包含userInfo字典資訊。

相關文章