1. 程式人生 > >iOS 多執行緒簡單整理NSThread、GCD、NSOperation

iOS 多執行緒簡單整理NSThread、GCD、NSOperation

iOS Pthreads  NSThread

Pthreads:可以在Unix / Linux / Windows 等系統跨平臺使用,使用 C 語言編寫,需要程式設計師自己管理執行緒的生命週期,使用難度較大

NSThread:是蘋果官方提供的,使用起來比 pthread 更加面向物件,簡單易用,可以直接操作執行緒物件。不過也需要需要程式設計師自己管理執行緒的生命週期(主要是建立),運用OC語言。

//使用類方法建立執行緒執行任務

+ (void)detachNewThreadWithBlock:(void (^)(void))block ;

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

//判斷當前是否為多執行緒

+ (BOOL)isMultiThreaded;

//設定當前執行緒優先順序//指定執行緒物件優先順序 0.0~1.0,預設值為0.5

+ (BOOL)setThreadPriority:(double)p;

//例項方法初始化,需要再呼叫start方法

- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument;

- (instancetype)initWithBlock:(void (^)(void))block;

另外,還有一個NSObject

的分類,瞅一眼:

//隱式的建立並啟動執行緒,並在指定的執行緒(主執行緒或子執行緒)上執行方法。

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;

執行緒相關用法

+ (NSThread *)mainThread; // 獲得主執行緒

- (BOOL)isMainThread;// 判斷是否為主執行緒(物件方法)

+ (BOOL)isMainThread;// 判斷是否為主執行緒(類方法)

NSThread *current = [NSThread currentThread]; // 獲得當前執行緒

- (void)setName:(NSString *)n;// 執行緒的名字——setter方法

  • (NSString *)name;// 執行緒的名字——getter方法

執行緒狀態控制方法

啟動執行緒方法 // 執行緒進入就緒狀態 -> 執行狀態。當執行緒任務執行完畢,自動進入死亡狀態

- (void)start;

阻塞(暫停)執行緒方法// 執行緒進入阻塞狀態

+ (void)sleepUntilDate:(NSDate *)date;//當前執行緒暫停到某個時間

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;//當前執行緒暫停一段時間

強制停止執行緒 // 執行緒進入死亡狀態

+ (void)exit; 退出當前執行緒

// 在主執行緒上執行操作

- (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;

iOS GCD

GCD:全名Grand Central Dispatch,中文名郭草地,是基於C語言的一套多執行緒開發API.替換NSThread等執行緒技術,充分利用了裝置多核(自動),使用C語言。

任務管理方式——佇列

兩個通用佇列:

序列佇列:所有任務會在一條執行緒中執行(有可能是當前執行緒也有可能是新開闢的執行緒),並且一個任務執行完畢後,才開始執行下一個任務。(等待完成)

並行佇列:可以開啟多條執行緒並行執行任務(但不一定會開啟新的執行緒),並且當一個任務放到指定執行緒開始執行時,下一個任務就可以開始執行了。(等待發生)

兩個特殊佇列:

主佇列:系統為我們建立好的一個序列佇列,牛逼之處在於它管理必須在主執行緒中執行的任務,屬於有勞保的。

全域性佇列:系統為我們建立好的一個並行佇列,使用起來與我們自己建立的並行佇列無本質差別。

任務執行方式(GCD給出了兩種執行方式——同步執行(sync)和非同步執行(async))

同步執行:在當前執行緒執行任務,不會開闢新的執行緒。必須等到Block函式執行完畢後,dispatch函式才會返回。

非同步執行:可以在新的執行緒中執行任務,但不一定會開闢新的執行緒。dispatch函式會立即返回, 然後Block在後臺非同步執行。

任務佇列組合方式

 

GCD其他函式用法

GCD 延時執行方法:dispatch_after//該函式用於任務延時執行

GCD 一次性程式碼(只執行一次):dispatch_once//保證函式在整個生命週期內只會執行一次

GCD 佇列組:dispatch_group//佇列組,當加入到佇列組中的所有任務執行完成之後,會呼叫dispatch_group_notify函式通知任務全部完成

GCD 柵欄方法:dispatch_barrier_async//使用此方法建立的任務,會查詢當前佇列中有沒有其他任務要執行,如果有,則等待已有任務執行完畢後再執行,同時,在此任務之後進入佇列的任務,需要等待此任務執行完成後,才能執行

GCD 快速迭代方法:dispatch_apply//該函式用於重複執行某個任務,如果任務佇列是並行佇列,重複執行的任務會併發執行,如果任務佇列為序列佇列,則任務會順序執行,需要注意的是,該函式為同步函式,要防止執行緒阻塞和死鎖

GCD 訊號量:dispatch_semaphore//訊號量是控制任務執行的重要條件,當訊號量為0時,所有任務等待,訊號量越大,允許可並行執行的任務數量越多

NSOperation && NSOperationQueue

NSOperation以及NSOperationQueue是蘋果對於GCD的封裝,其中呢,NSOperation其實就是我們上面所說的任務,但是這個類不能直接使用,我們要用他的兩個子類,NSBlockOperation和NSInvocationOperation,而NSOperationQueue呢,其實就是類似於GCD中的佇列,用於管理你加入到其中的任務。

NSOperation

它提供了關於任務的執行,取消,以及隨時獲取任務的狀態,新增任務依賴以及優先順序等方法和屬性,相對於GCD提供的方法來說,更直觀,更方便,並且提供了更多的控制介面。

- (void)start;//啟動任務 預設加入到當前佇列

- (void)main;//自定義NSOperation,寫一個子類,重寫這個方法,在這個方法裡面新增需要執行的操作。

- (void)addDependency:(NSOperation *)op;//新增依賴

- (void)removeDependency:(NSOperation *)op;//移除依賴

@property NSOperationQueuePriority queuePriority;//執行優先順序

然而NSOperation本身是個抽象類,不能直接使用,我們有三種方式賦予它新的生命,如下

NSOperation第一個,這是我要說的第一個任務型別,我們可以自定義繼承於NSOperation的子類,並重寫父類提供的方法,自定義的任務更具有指向性,它可以滿足你特定的需求

NSBlockOperation 第二個,就是系統提供的NSOperation的子類NSBlockOperation,我們看一下他提供的API:

@interface NSBlockOperation : NSOperation {

@private

id _private2;

void *_reserved2;

}

+ (instancetype)blockOperationWithBlock:(void (^)(void))block;

- (void)addExecutionBlock:(void (^)(void))block;

@property (readonly, copy) NSArray *executionBlocks;

@end

NSInvocationOperation 第三個,就是它了,同樣也是系統提供給我們的一個任務類,基於一個target物件以及一個selector來建立任務,具體程式碼:

-(void)NSInvocationOperationRun{

NSInvocationOperation *invocationOper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperSel) object:nil];

[invocationOper start];

}

-(void)invocationOperSel{

NSLog(@"NSInvocationOperationRun_%@",[NSThread currentThread]);

}

NSOperationQueue

上面說道我們建立的NSOperation任務物件可以通過start方法來執行,同樣我們可以把這個任務物件新增到一個NSOperationQueue物件中去執行

- (void)addOperation:(NSOperation *)op;//新增任務

- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait NS_AVAILABLE(10_6, 4_0);//新增一組任務

- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);//新增一個block形式的任務

-(void)NSOperationQueueRun{

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

NSInvocationOperation *invocationOper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperSel) object:nil];

[queue addOperation:invocationOper];

NSBlockOperation *blockOper = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"NSBlockOperationRun_%@",[NSThread currentThread]);

}];

[queue addOperation:blockOper];

[queue addOperationWithBlock:^{

NSLog(@"QUEUEBlockOperationRun_%@",[NSThread currentThread]);

}];

}

任務的優先順序

新增依賴關係

佇列的最大併發數

執行緒鎖 NSLock @synchronized(要傳入一個同步物件(一般就是self),然後將你需要加鎖的資源放入程式碼塊中,如果該資源有執行緒正在訪問時,會讓其他執行緒等待)