创建常驻子线程
说明:
将线程对象中添加runLoop,runLoop中添加port(抽象端口消息收发),成为常驻子线程。
销毁常驻子线程
说明:
原理为管理runloop状态并释放runloop循环,不再常驻,线程随之自动释放。
注:不可以直接移除port或强制杀死thread,容易产生野指针。
举例
#import "thread.h"
@interface thread()
@property(nonatomic,assign)BOOL shouldStopRun;
@property(nonatomic,strong)NSPort *port;
@property(nonatomic,strong)NSThread *thread;
@end
@implementation thread
- (void)done{
self.shouldStopRun = NO;
self.port = [NSMachPort port];
//添加runLoop,抽象端口port消息收发,成为常驻子线程
self.thread = [[NSThread alloc]initWithTarget:self selector:@selector(AddRunLoop) object:nil];
[self.thread start];
}
- (void)AddRunLoop{
//TLS:线程局部存储空间,只能被当前线程访问
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:self.port forMode:NSDefaultRunLoopMode];
//2秒后释放runloop两层循环,不再常驻,释放线程
[self performSelector:@selector(RemoveRunLoop) withObject:nil afterDelay:2];
//执行并等待释放
//[runloop run]; 底层源码等价于[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]
while (!self.shouldStopRun && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
}
}
- (void)RemoveRunLoop{
//正确释放
self.shouldStopRun = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
//错误释放(移除当前source事件时,不会保证系统不会向runloop中添加其他事件源,会产生野指针)
// [[NSRunLoop currentRunLoop] removePort:self.port forMode:NSDefaultRunLoopMode];
//错误释放(thread被释放,但runloop仍存活,会产生野指针)
// [NSThread exit];
}
@end