Runloop可以做什么?
- 处理Crash
- 保持线程存活(线程保活)
- 监测、优化卡顿
子线程执行完任务之后会自动销毁
线程跟Runloop有什么关系?
线程跟Runloop一一对应,并且是以键值对存储的(线程:Runloop => key:value)
Runloop的组成
Runloop的组成:Mode->sources/timer/observer (observer负责观察runloop的状态,对runloop的启动和休眠不起作用)
如果Runloop的Mode里面没有sources、timer的话,Runloop会直接进入休眠状态
sources1:基于port的内核事件,可以主动唤醒 (数据结构:machport:sources1)
sources0:非基于port,不能主动唤醒 (数据结构:数组)
#mark pragma - 线程保护
-(IBAction)keepAliveAction:(UIButton *)sender{
static dispatch_once_t onceToken;
self.stop = NO;
dispatch_once(&onceToken, ^{
testThread = [[MyThread alloc] initWithTarget:self selector:@selector(doSomething) object:nil];
[testThread setName:@"线程保活"];
[testThread start];
})
}
-(void)doSomething{
@autoreleasepool{
NSLog(@"%@",[NSThread currentThread]); // testThread
NSRunloop *runloop = [NSRunloop currentRunloop];
// 添加port或者timer来唤醒runloop(如果不添加,runloop将进入休眠)
[runloop addPort:[NSMachPort port] forMode:NSRunloopCommonModes]; // sources1
// [runloop addTimer: forMode:]
// CFRunloopAddSource()
// 使用[runloop runMode: beforeDate:] 代替 [runloop run],设置一个布尔值来
while(!self.stop) {
[runloop runMode:NSDefaultRunloopMode beforeDate:[NSDate distantFuture]];
}
// [runloop run];
NSlog(@"结束"); // runloop被唤醒则不会执行到这一行(如果runloop进入休眠,则会打印结束)
}
#mark pragma - 执行任务
-(IBAction)performTask:(UIButton *)sender{
[self performSelector:@selector(addSubThreadAction) onThread:testThread withObject:nil waitUntilDone:NO];
}
-(void)addSubThreadAction{
// 线程保活需要做的操作写到这里
// 停止 (只能停止单次循环,run方法会多次调用runMode: beforeDate:)
self.stop = YES;
testThread = nil; // 停止强引用
CFRunloopStop(CFRunloopGetCurrent());
}
NSRunloop和CFRunloopRef的区别:
- CFRunloopRef纯C语言实现,线程安全;
- NSRunloop是面向对象的,不是线程安全的。