今天跟朋友讨论一个问题,就是如何实现一个线程的常驻,作为一个iOS
开发者,一开始想到的当然是通过runloop
来对线程保活,保证线程的常驻;但是除此之外还有其他的方式吗?如果其他的语言没有runloop
特性,那它们是如何来保证线程的常驻的,比如说GCD
线程池里面的核心线程,是怎样做到常驻的,它应该是C语言
实现的,是没有runloop
这里的特性的。
我想了下,线程池
里面的核心线程
的处理逻辑,应该跟runloop
的跑圈逻辑是一致的。核心线程
执行的是一个死循环
的处理逻辑,在这个逻辑里面有任务就处理,没有任务就进入休眠状态,等到新任务到来,再次唤醒,执行任务。
因为这里存在休眠和唤醒状态,所以应该有一个信号量
,信号量
初始化为0
,当有新任务到来时,信号量
加1
,然后将任务
放到队列
里面,这时候线程
被唤醒,将信号量
减1
,然后从任务队列
里面取出任务
,开始执行任务。
按照这个思路实现了下常驻线程
,代码如下:
#import "FJFPermanentThread.h"
@implementation FJFPermanentThread {
NSMutableArray *_actionMarray;
NSThread *_thread;
dispatch_semaphore_t _semaphore;
dispatch_semaphore_t _arraySemaphore;
bool _cancel;
}
#pragma mark - Life Circle
- (instancetype)init {
if (self = [super init]) {
_actionMarray = [NSMutableArray array];
// 创建 信号量
_semaphore = dispatch_semaphore_create(0);
// 保证 数组 操作 原子性
_arraySemaphore = dispatch_semaphore_create(1);
// 创建 线程
_thread = [[NSThread alloc] initWithTarget:self selector:@selector(handleMessage) object:nil];
[_thread start];
}
return self;
}
#pragma mark - Public Methods
-(void)doAction:(dispatch_block_t)action {
if (!_cancel) {
// 将任务 放入数组
[self actionMarryAddObject:[action copy]];
// 信号量 加1
dispatch_semaphore_signal(_semaphore);
}
}
- (void)cancel {
_cancel = YES;
// 线程 取消后,清空所有回调
[self actionMarryRemoveAllObject];
// 相当于 发送一个 任务终止 信号
dispatch_semaphore_signal(_semaphore);
}
#pragma mark - Private Methods
// 处理 消息
- (void)handleMessage {
while (true) {
// 等待信号量,信号量减1
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
// 收到信号
if (_cancel) {
break;
}
// 开始执行任务
dispatch_block_t block = [self actionMarryFirstObject];
if (block) {
block();
[self actionMarryRemoveObject:block];
}
}
}
- (void)actionMarryAddObject:(id)object {
dispatch_semaphore_wait(_arraySemaphore, DISPATCH_TIME_FOREVER);
[_actionMarray addObject:object];
dispatch_semaphore_signal(_arraySemaphore);
}
- (void)actionMarryRemoveObject:(id)object {
dispatch_semaphore_wait(_arraySemaphore, DISPATCH_TIME_FOREVER);
[_actionMarray removeObject:object];
dispatch_semaphore_signal(_arraySemaphore);
}
- (void)actionMarryRemoveAllObject {
dispatch_semaphore_wait(_arraySemaphore, DISPATCH_TIME_FOREVER);
[_actionMarray removeAllObjects];
dispatch_semaphore_signal(_arraySemaphore);
}
- (dispatch_block_t)actionMarryFirstObject {
dispatch_semaphore_wait(_arraySemaphore, DISPATCH_TIME_FOREVER);
dispatch_block_t block = [_actionMarray firstObject];
dispatch_semaphore_signal(_arraySemaphore);
return block;
}
@end
网友评论