NSThread 是蘋果官方提供的,使用起來比 pthread 更加面向對象,簡單易用,可以直接操作線程對象。不過也需要需要程序員自己管理線程的生命周期(主要是創建),我們在開發的過程中偶爾使用 NSThread。比如我們會經常調用[NSThread currentThread]來顯示當前的進程信息
NSThread的創建與運行
//使用target對象的selector作為線程的任務執行體,該selector方法最多可以接收一個參數,該參數即為argument
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument
//使用block作為線程的任務執行體
- (instancetype)initWithBlock:(void (^)(void))block
/*
類方法,返回值為void
使用一個block作為線程的執行體,并直接啟動線程
上面的實例方法返回NSThread對象需要手動調用start方法來啟動線程執行任務
*/
+ (void)detachNewThreadWithBlock:(void (^)(void))block
/*
類方法,返回值為void
使用target對象的selector作為線程的任務執行體,該selector方法最多接收一個參數,該參數即為argument
同樣的,該方法創建完縣城后會自動啟動線程不需要手動觸發
*/
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument
簡單運用
- (void)viewDidLoad {
[super viewDidLoad];
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(firstThread:) object:@"Hello, World"];
//設置線程的名字,方便查看
[thread setName:@"firstThread"];
//啟動線程
[thread start];
}
//線程的任務執行體并接收一個參數arg
- (void)firstThread:(id)arg
{
NSLog(@"Task %@ %@", [NSThread currentThread], arg);
NSLog(@"Thread Task Complete");
}
常見API
// 獲得主線程
+ (NSThread *)mainThread;
// 判斷是否為主線程(對象方法)
- (BOOL)isMainThread;
// 判斷是否為主線程(類方法)
+ (BOOL)isMainThread;
// 獲得當前線程
NSThread *current = [NSThread currentThread];
// 線程的名字——setter方法
- (void)setName:(NSString *)n;
// 線程的名字——getter方法
- (NSString *)name;
線程狀態控制方法
// 線程進入就緒狀態 -> 運行狀態。當線程任務執行完畢,自動進入死亡狀態
- (void)start;
// 線程進入阻塞狀態
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
//強制停止線程 線程進入死亡狀態
+ (void)exit;
線程之間的通信
在開發中,我們經常會在子線程進行耗時操作,操作結束后再回到主線程去刷新 UI。這就涉及到了子線程和主線程之間的通信。我們先來了解一下官方關于 NSThread 的線程間通信的方法。
// 在主線程上執行操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
// equivalent to the first method with kCFRunLoopCommonModes
// 在指定線程上執行操作
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
// 在當前線程上執行操作,調用 NSObject 的 performSelector:相關方法
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
線程的狀態轉換
當我們新建一條線程NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];,在內存中的表現為:
當調用[thread start];后,系統把線程對象放入可調度線程池中,線程對象進入就緒狀態,如下圖所示。
- 如果CPU現在調度當前線程對象,則當前線程對象進入運行狀態,如果CPU調度其他線程對象,則當前線程對象回到就緒狀態。
- 如果CPU在運行當前線程對象的時候調用了sleep方法\等待同步鎖,則當前線程對象就進入了阻塞狀態,等到sleep到時\得到同步鎖,則回到就緒狀態。
- 如果CPU在運行當前線程對象的時候線程任務執行完畢\異常強制退出,則當前線程對象進入死亡狀態。
結語
以上就是這篇文章的全部內容了,希望本文的內容對大家具有一定的參考學習價值,同時歡迎大家進入小編 iOS 交流群:624212887,一起交流學習,謝謝大家的支持