【iOS】從實際出發理解多線程(二)--NSThread基礎操做

簡介ios

NSthread是蘋果官方提供面向對象操做線程的技術,簡單方便,能夠直接操做線程對象,不過須要本身控制線程的生命週期。在平時使用較少,經常使用的就是下面的方法來獲取當前線程。macos

[NSThread currentThread]

使用編程

1.實例初始化、屬性和實例方法數組

初始化函數

切記下面兩個方法初始化的NSThread必須手動start開啓線程
//建立線程
NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"Thread"];
//或者
NSThread  *newThread=[[NSThread alloc]init];
NSThread  *newThread= [[NSThread alloc]initWithBlock:^{
  NSLog(@"initWithBlock");
}];

屬性oop

線程字典ui

/**
每一個線程都維護了一個鍵-值的字典,它能夠在線程裏面的任何地方被訪問。
你可使用該字典來保存一些信息,這些信息在整個線程的執行過程當中保持不變。
好比,你可使用它來存儲在你的整個線程過程當中 Run loop 裏面屢次迭代的狀態信息。
NSThread實例可使用如下方法
*/

@property (readonly, retain) NSMutableDictionary *threadDictionary;
NSMutableDictionary *dict = [thread threadDictionary];  

 

優先級spa

@property double threadPriority ; //優先級

線程優先級線程

/** NSQualityOfService:
  NSQualityOfServiceUserInteractive:最高優先級,主要用於提供交互UI的操做,好比處理點擊事件,繪製圖像到屏幕上
  NSQualityOfServiceUserInitiated:次高優先級,主要用於執行須要當即返回的任務
  NSQualityOfServiceDefault:默認優先級,當沒有設置優先級的時候,線程默認優先級
  NSQualityOfServiceUtility:普通優先級,主要用於不須要當即返回的任務
  NSQualityOfServiceBackground:後臺優先級,用於徹底不緊急的任務
*/
@property NSQualityOfService qualityOfService

線程名稱調試

@property (nullable, copy) NSString *name;

線程使用棧區大小,默認是512k

@property NSUInteger stackSize ;

線程狀態(正在執行、執行結束、是否能夠取消)

@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;

實例方法

// 啓動線程  實例化線程須要手動啓動才能運行
- (void)start;
[thread stary]


// 是否爲主線程
- (BOOL)isMainThread; 
isMain = [thread isMainThread];

//設置線程名稱
- (void)setName:(NSString *) name;
[thraed setName:@"name"];

// 取消線程 
- (void)cancel;
[thread  cancel];

// 線程的入口函數
- (void)main; 
[thread main];

// 線程是否正在執行
- (void)isExecuting;
isRunning=[thread isExecuting];

// 線程是否已經結束
- (void)isFinished;
isEnd=[thread isFinished];

// 線程是否撤銷
- (void)isCancelled;
isCancel=[thread isCancelled];

類建立方法

/*
   建立子線程並開始
   建立後就可執行,不須要手動開啓
可是不能獲取NSThread對象
*/ /** block方式 具體的任務在Block中執行 */ + (void)detachNewThreadWithBlock:(void (^)(void))block; /** SEL方式 利用selector方法初始化NSThread,target指selector方法從屬於的對象 selector方法也 是指定的target對象的方法 */ + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

類使用方法

// 獲取當前線程
+ (void)currentThread;
[NSThread currentThread];

//當前代碼運行所在線程是否爲子線程
+ (BOOL)isMultiThreaded;
isMulti = [NSThread isMultiThreaded];

// 當前代碼所在線程睡到指定時間  
+ (void)sleepUntilDate: (NSDate *)date; 
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

// 線程沉睡時間間隔,這個方法在設置啓動頁間隔的時候比較常見
+ (void)sleepForTimeInterval: (NSTimeInterval)time;
[NSThread sleepForTimeInterval:1.0];

// 退出當前線程
+ (void)exit;
[NSThread exit];

// 設置當前線程優先級
+ (double)threadPriority;
double dPriority=[NSThread threadPriority];

// 給當前線程設定優先級,調度優先級的取值範圍是0.0 ~ 1.0,默認0.5,值越大,優先級越高。
+ (BOOL)setThreadPriority:(double)priority;
BOOL isSetting=[NSThread setThreadPriority:(0.0~1.0)];

// 線程的調用都會有行數的調用函數的調用,就會有棧返回地址的記錄,
在這裏返回的是函數調用返回的虛擬地址
說白了就是在在該先出中函數調用的虛擬地址的數組
+ (NSArray *)callStackReturnAddresses;
NSArray *addressArray=[NSThread callStackReturnAddresses];

// 同上面的方法同樣,只不過返回的是該線程調用函數的名字數字
+ (NSArray *)callStackSymbols;
NSArray* nameNumArray=[NSThread callStackSymbols];

注意:callStackReturnAddress和callStackSymbols這兩個函數能夠同NSLog聯合使用來跟蹤線程的函數調用狀況,是編程調試的重要手段

 隱式建立&線程間通信

如下方法位於NSObject(NSThreadPerformAdditions)分類中,全部繼承自NSObject實例化對象均可以調用如下方法。

/**
  指定方法在主線程中執行
  參數1. SEL 方法
    2.方法參數
    3.BOOL類型  表示是否等待當前aSelector方法執行完畢
    4.指定的Runloop model
*/
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes
/**
  指定方法在某個線程中執行
  參數1. SEL 方法
    2.方法參數
    3.是否等待當前執行完畢
    4.指定的Runloop model
*/
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    // equivalent to the first method with kCFRunLoopCommonModes
/**
  指定方法在開啓的子線程中執行
  參數1. SEL 方法
    2.方法參數
*/
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

注意:咱們提到的線程間通信就是這幾個方法,沒有多高大上多複雜。

再注意:蘋果聲明UI更新必定要在UI線程(主線程)中執行,雖然不是全部後臺線程更新UI都會出錯。

再注意:waitUntilDone後面的這個BOOL類型的參數,這個參數的意義有點像咱們是否同步執行aSelector這個任務!具體的看下面兩張圖的內容就一目瞭然了。

 

 

相關文章
相關標籤/搜索