RunLoop

作者: Oh丶Really | 来源:发表于2020-07-24 02:38 被阅读0次
    • 概念
    • 数据结构
    • 事件循环机制
    • RunLoop 与 NSTimer
    • RunLoop 与多线程

    一、概念

    • RunLoop是通过内部维护的事件循环对事件/消息进行管理的一个对象

    事件循环:

    • 没有消息需要处理时,休眠以避免资源占用(用户态--> 内核态)
    • 有消息需要处理,立刻被唤醒(内核态 --> 用户态)
    系统调用相关指令如开关机等是在内核态的,程序一般运行在用户态的,绝大部分API都是用户态的
    image

    二、数据结构

    NSRunLoop 是 CFRunLoop 的封装,提供了面相对象的API,其数据结构如下:

    • CFRunLoop
    • CFRunLoopMode
    • Source/Timer/Observer

    1、CFRunLoop

    包含以下内容:

    • pthread --- (RunLoop和线程一一对应)
    • currentMode --- CFRunLoopMode
    • modes --- NSMutableSet<CFRunLoopMode*>
    • commonModes --- NSMutableSet<NSString*>
    • commonModeItems --- 也是一个集合,包含多个 Observer(观察者)、Timer、Source

    2、CFRunLoopMode

    • name --- 名称,如 NSDefaultRunLoopMode 等
    • sources0 -- 集合类型,无序的
    • sources1 --- 集合类型
    • observers --- 数组,有序的
    • timers --- 数组

    3、CFRunLoopSource

    • source0 --- 需要手动唤醒线程
    • source1 --- 具备唤醒线程的能力

    4、CFRunLoopTimer

    • 基于事件的定时器,和 NSTimer 是 toll-free bridged的。(即可以桥转换)

    5、CFRunLoopObserver

    观测时间点:

    • kCFRunLoopEntry
    • kCFRunLoopBeforeTimers
    • kCFRunLoopBeforeSources
    • kCFRunLoopBeforeWaiting --- 即将休眠,即将切换内核状态
    • kCFRunLoopAfterWaiting --- 内核态切换到用户态不久之后发出
    • kCFRunLoopExit

    各个数据结构之间的关系

    一对多的关系:


    image

    RunLoop的Mode:

    问题:怎样将Timer同时添加到两个mode?以保证mode切换的时候,不影响timer的使用
    image
    解决 :NSRunLoopCommonModes
    NSRunLoopCommonModes的特殊性
    • commonMode 不是实际存在的一种Mode
    • 是同步 Source/Timer/Observer 到多个 Mode 中的一种技术方案

    三、事件循环机制

    image
    APP运行生命周期内RunLoop的整体事件循环机制

    RunLoop的核心

    image

    四、RunLoop 与 NSTimer

    问题:滑动 TableView 时,定时器还会生效吗?
    回答:不会生效,timer 默认加入到 defaultMode 中,滑动的时候,Mode 会从 kCFRunLoopDefaultMode 切换到 UITrackingRunLoopMode,不同的 Mode ,timer 不相关,所以不生效
    解决:添加到 kCFRunLoopCommonMode 中

    五、RunLoop 与多线程

    • 线程是和 RunLoop 一一对应的
    • 自己创建的线程默认是没有 RunLoop 的

    怎样实现一个常驻线程

    • 为当前线程开启一个 RunLoop
    • 向该 RunLoop 中添加一个 Port/Source 等维持 RunLoop 的事件循环
    • 启动该 RunLoop

    代码实现:

    运行的模式和资源添加的模式一定要是同一个
    image
    image

    总结

    • 什么是 RunLoop ,是怎样做到有事做事,没事休息的?
    • RunLoop 与线程的关系?
    • 如何实现常驻线程?
    • 怎样保证子线程数据回来更新UI的时候,不打断用户的滑动操作?(把子线程抛给主线程的操作添加到 DefaultMode 下,此时滑动 UITrackingRunLoopMode 不受影响)

    相关文章

      网友评论

          本文标题:RunLoop

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