Runloop基本原理

① Runloop可以做什么?
  1. 保住线程,处理crash

场景:在捕获异常的时候,强制程序Runloop,就不会发生闪退的情况
拓展:iOS runloop解决App crash并获取日志

// 核心代码部分
/*在主线程中调用堆栈中异常信号,当捕获到异常信号的时候,用Runloop保住线程,以致于程序不会立马crash*/
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (true) {
  for (NSString *mode in (__bridge NSArray *)allModes) {
    // 快速切换Mode -> CFRunLoopRunInMode
    CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
  }
}
  1. 线程保活 (4种保活方式:NSThread / NSOperation / GCD / NSCondition(条件锁))

场景:创建很多子线程执行完任务后,会自动销毁,但频繁创建后又销毁会造成资源浪费,所以可以用Runloop进行线程保活
拓展:NSThread、GCD、NSOperation多线程区别

  1. 监测卡顿

场景:造成卡顿主要原因耗时操作造成主线程阻塞,比如大量的:数据解析、动画加载、图片绘制、文件下载等
拓展:YYFPSLabel讲解

② Runloop跟线程有什么关系?
  • 一一对应,键值对形式存储 Key(线程) : Value(Runloop)
    具体方法见Foundation -> CFRunloop.c -> CFRunloopGet0 1422行代码
③ Runloop的组成?
  • Mode -> sources(事件源) / timer(定时器) / observer(监测)

如果子线程sources或者timer为null(而主线程可为null),Runloop会直接休眠
具体方法见Foundation -> CFRunloop.c -> __CFRunloopModeIsEmpty 870行代码

CFRunloopRef 和 NSRunloop 区别
CFRunloopRef是纯C语言实现的,线程安全
NSRunloop是封装的面向对象语言,线程不安全

sources中有sources0sources1
sources0:非port事件,用来处理手动触发的事件。例如:滑动、点击等
sources1:系统port的内核事件源,可以通过内核和其它线程之间发消息,还可以主动唤醒Runloop

observer:适用场景卡顿监测(硬件有关:CPU程序指令、GPU图像渲染)
1.影响CPU性能的因素:IO任务、过多的线程抢占CPU资源、温度过高降频
2.影响GPU性能的因素:显存频率、渲染算法、大计算量

/*子线程监测主线程:使用 CFRunLoopAddObserver 检测主线程是否卡顿*/
//将观察者添加到主线程runloop的common模式下的观察中 
CFRunLoopAddObserver(CFRunLoopGetMain(), runLoopObserver, kCFRunLoopCommonModes);
④ Runloop的如何启动和停止?

【启动方式】

  • 无条件启动(最简单,最不可取,会引起死循环)
[[NSRunloop currentRunLoop] run];
/*本质是while调用[[NSRunloop currentRunLoop] runModel:NSDefaultLoopMode beforeDate:[NSDate distantFuture]];*/
  • 设置超时时间
[[NSRunloop currentRunLoop] runUntilDate:[NSDate distantFuture]];
/*本质是while调用[[NSRunloop currentRunLoop] runModel:NSDefaultLoopMode beforeDate:[NSDate distantFuture]];*/
  • 特殊模式
[[NSRunloop currentRunLoop] runModel:NSDefaultLoopMode beforeDate:[NSDate distantFuture]];

【停止方式】

  • 线程停止强引用
CFRunLoopStop(CFRunLoopGetCurrent());
// NSThread
self.thread = nil;

你可能感兴趣的:(Runloop基本原理)