iOS:常駐執行緒

搬磚的碼農發表於2019-01-15

常駐執行緒

在實際的專案中,根據需求我們可能需要在後臺常駐一個執行緒做一些事情。而對於常駐執行緒搜尋下的話會有很多解決方案,但是大多數都是提到使用NSThreadRunLoop來實現的。而在本篇中介紹另外一種實現方法,那就是採用訊號量的方式來實現。什麼是訊號量?我這裡簡單的解釋下

訊號量主要是用在多執行緒的場景,一個執行緒等待訊號直到接收到訊號繼續執行,另外一個執行緒傳送訊號通知等待的執行緒繼續執行。

訊號量的執行方式正好跟我們需要的常駐執行緒的需求是契合的。在沒有任務的時候讓該執行緒處於等待狀態,等有任務了,那麼傳送一個訊號讓常駐執行緒執行我們的任務。

下面是實現的程式碼:

/** 常駐執行緒 */@interface ResidentThread : NSObject-(void)doAction:(dispatch_block_t)action;
-(void)cancel;
@end@implementation ResidentThread{
NSMutableArray *actions;
NSThread *thread;
dispatch_semaphore_t sem;
bool cancel;

}-(id)init{
self = [super init];
actions = [NSMutableArray array];
// 建立訊號量 sem = dispatch_semaphore_create(0);
// 建立一個新執行緒 thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
return self;

}-(void)run{
while (true) {
// 等待訊號量 dispatch_semaphore_wait(sem, -1);
// 收到訊號 // 如果執行緒已經取消了,那麼退出迴圈 if(cancel){
break;

} // 開始執行任務 dispatch_block_t block = [actions firstObject];
if(block){
[actions removeObject:block];
block();

}
}
}// 執行某個任務-(void)doAction:(dispatch_block_t)action{
if(!cancel){
// 如果執行緒已經cancel了,那麼直接忽略 // 將任務放入陣列 [actions addObject:[action copy]];
// 傳送訊號 dispatch_semaphore_signal(sem);

}
}// 終止常駐執行緒-(void)cancel{
cancel = YES;
// 執行緒取消後,清空所有的回撥 [actions removeAllObjects];
// 相當於傳送一個終止任務的訊號 dispatch_semaphore_signal(sem);

}@end複製程式碼

上面程式碼中使用了GCD的訊號量,本來想使用semaphore.h標頭檔案中的訊號量API的,但是這裡面的API已經被蘋果DEPRECATED了,就算你強制使用,那麼也無法初始化訊號量。

下面分析程式碼:ResidentThread對外總共提供了兩個方法,分別是doAction:cancel

  1. doAction::這個方法接收一個dispatch_block_t的引數,代表實際需要讓常駐執行緒執行的任務。
  2. cancel:終止該常駐執行緒。

    為了安全起見,這裡採用的是標記位的方式。另外要注意到,cancel方法裡面額外傳送了一個訊號,這個訊號的作用類似於傳送了一個終止任務的訊號

從上面的程式碼中可以看出,常駐執行緒的原理是很簡單的,而且在實現上也很簡單。並且你會發現,這裡面的任務其實是序列執行的。

Runloop

Runloop的原理我就不多介紹了,掘金裡面有很多分析文章,講的也很透徹,甚至有些直接把原始碼都貼出來分析。

從上面的常駐執行緒的程式碼中可以看出來,run方法的內部就是一個while迴圈,迴圈等待訊號,當接收到訊號後立馬執行任務。執行完任務後繼續等待訊號。這樣一個流程其實是跟Runloop的工作原理是差不多的。Runloop也是一個等待訊號>
收到訊號>
執行回撥>
繼續等待訊號,這樣一個流程。

事實上,這樣一套程式碼,在其他語言中比如C、C++上差不多就是這樣實現。

如果進一步的發散下呢?GCD的任務排程的實現是不是也類似這樣呢?事實上,我曾今在寫C的時候,就是使用上面的程式碼實現多執行緒的任務排程功能。

來源:https://juejin.im/post/5c3c61956fb9a049e93cf9f2

相關文章