美文网首页
runloop笔记

runloop笔记

作者: 下班买鸡蛋 | 来源:发表于2020-05-19 16:25 被阅读0次

    一、RunLoop概念

    1、没有消息处理时,休眠已避免资源占用,由用户态切换到内核态

    2、有消息需要处理时,立刻被唤醒,由内核态切换到用户态

    二、RunLoop的数据结构

    CFRunLoop:RunLoop对象

    CFRunLoopMode:运行模式

    CFRunLoopSource:输入源/事件源

    CFRunLoopTimer:定时源

    CFRunLoopObserver:观察者

    1.CFRunLoop:由pthread(线程对象,说明RunLoop和线程是一一对应的)、currentMode(当前所处的运行模式)、modes(多个运行模式的集合)、commonModes(模式名称字符串集合)、commonModelItems(Observer,Timer,Source集合)构成

    2、CFRunLoopMode

    由name、source0、source1、observers、timers构成

    3、CFRunLoopSource

    分为source0和source1两种

    source0:

    只有一个回调,也就是函数指针。不会自动调用,需要先将这个source标记为待处理,再手动唤醒runloop让其处理这个事件。

    source1:

    基于port的,也就是接收系统发出的事件,比如用户触摸屏幕,系统会发送个触摸事件到当前进程,进而唤醒进程中线程中的runloop。

    具备唤醒线程的能力

    4、CFRunLoopTimer

    基于时间的触发器,基本上说的就是NSTimer。在预设的时间点唤醒RunLoop执行回调。因为它是基于RunLoop的,因此它不是实时的(就是NSTimer 是不准确的。 因为RunLoop只负责分发源的消息。如果线程当前正在处理繁重的任务,就有可能导致Timer本次延时,或者少执行一次)。

    5、CFRunLoopObserver

    监听以下时间点:CFRunLoopActivity

    kCFRunLoopEntry

    RunLoop准备启动

    kCFRunLoopBeforeTimers

    RunLoop将要处理一些Timer相关事件

    kCFRunLoopBeforeSources

    RunLoop将要处理一些Source事件

    kCFRunLoopBeforeWaiting

    RunLoop将要进行休眠状态,即将由用户态切换到内核态

    kCFRunLoopAfterWaiting

    RunLoop被唤醒,即从内核态切换到用户态后

    kCFRunLoopExit

    RunLoop退出

    kCFRunLoopAllActivities

    监听所有状态

    6、各数据结构之间的联系

    线程和RunLoop一一对应, RunLoop和Mode是一对多的,Mode和source、timer、observer也是一对多的

    三、RunLoop的Mode

    关于Mode首先要知道一个RunLoop 对象中可能包含多个Mode,且每次调用 RunLoop 的主函数时,只能指定其中一个 Mode(CurrentMode)。切换 Mode,需要重新指定一个 Mode 。主要是为了分隔开不同的 Source、Timer、Observer,让它们之间互不影响

    当RunLoop运行在Mode1上时,是无法接受处理Mode2或Mode3上的Source、Timer、Observer事件的

    总共是有五种CFRunLoopMode:

    kCFRunLoopDefaultMode:默认模式,主线程是在这个运行模式下运行

    UITrackingRunLoopMode:跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)

    UIInitializationRunLoopMode:在刚启动App时第进入的第一个 Mode,启动完成后就不再使用

    GSEventReceiveRunLoopMode:接受系统内部事件,通常用不到

    kCFRunLoopCommonModes:伪模式,不是一种真正的运行模式,是同步Source/Timer/Observer到多个Mode中的一种解决方案

    对于RunLoop而言最核心的事情就是保证线程在没有消息的时候休眠,在有消息时唤醒,以提高程序性能。RunLoop这个机制是依靠系统内核来完成的(苹果操作系统核心组件Darwin中的Mach)。

    RunLoop通过mach_msg()函数接收、发送消息。它的本质是调用函数mach_msg_trap(),相当于是一个系统调用,会触发内核状态切换。在用户态调用mach_msg_trap()时会切换到内核态;内核态中内核实现的mach_msg()函数会完成实际的工作。

    即基于port的source1,监听端口,端口有消息就会触发回调;而source0,要手动标记为待处理和手动唤醒RunLoop

    四、Runloop和线程

    线程和RunLoop是一一对应的,其映射关系是保存在一个全局的 Dictionary 里

    自己创建的线程默认是没有开启RunLoop的

    相关文章

      网友评论

          本文标题:runloop笔记

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