为了避免频繁的创建线程,我们可以利用runloop来设计一个保活线程。
需要注意的点
run和runmode的区别
[NSRunLoop currentRunLoop] 调用run方法,永远都停不下来。
[NSRunLoop currentRunLoop] 调用runmode方法,会在一次循环之后停止。
子线程默认不会开启runloop
我们需要手动添加port来开启runloop
需要注意我们要设计的是一个子线程保活,当然关闭runloop的时候,也要关闭子线程的runloop
[self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES]
我们需要注意waitUntilDone这个参数,当设置为YES的时候,会等待performSelector执行完,才会执行后面的。如果设为NO则不会等待。
保活线程的销毁时机,是在调用dealloc的时候先进行停止在销毁。我们需要注意,在thread销毁过程中,while函数还在执行,要判断self是否还存在,防止直接调用self.stop造成的野指针错误
#import <Foundation/Foundation.h>
typedef void (^XHKeepAliveThreadTask)(void);
@interface XHKeepAliveThread : NSObject
/**
开启线程
*/
//- (void)run;
/**
在当前子线程执行一个任务
*/
- (void)executeTask:(XHKeepAliveThreadTask)task;
/**
结束线程
*/
- (void)stop;
@end
#import "XHKeepAliveThread.h"
@interface XHThread : NSThread
@end
@implementation XHThread
- (void)dealloc
{
NSLog(@"%s", __func__);
}
@end
@interface XHKeepAliveThread()
@property (strong, nonatomic) XHThread *innerThread;
@property (assign, nonatomic, getter=isStopped) BOOL stopped;
@end
@implementation XHKeepAliveThread
#pragma mark - public methods
- (instancetype)init
{
if (self = [super init]) {
self.stopped = NO;
__weak typeof(self) weakSelf = self;
self.innerThread = [[XHThread alloc] initWithBlock:^{
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
while (weakSelf && !weakSelf.isStopped) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}];
[self.innerThread start];
}
return self;
}
//- (void)run
//{
// if (!self.innerThread) return;
//
// [self.innerThread start];
//}
- (void)executeTask:(XHKeepAliveThreadTask)task
{
if (!self.innerThread || !task) return;
[self performSelector:@selector(__executeTask:) onThread:self.innerThread withObject:task waitUntilDone:NO];
}
- (void)stop
{
if (!self.innerThread) return;
[self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}
- (void)dealloc
{
NSLog(@"%s", __func__);
[self stop];
}
#pragma mark - private methods
- (void)__stop
{
self.stopped = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
self.innerThread = nil;
}
- (void)__executeTask:(XHKeepAliveThreadTask)task
{
task();
}
@end
网友评论