美文网首页
Runloop基本原理

Runloop基本原理

作者: 胡智钦 | 来源:发表于2022-04-12 11:08 被阅读0次
    ① 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基本原理

          本文链接:https://www.haomeiwen.com/subject/mcigsrtx.html