Runloop原理(二)

作者: erlich | 来源:发表于2022-06-22 17:31 被阅读0次

Runloop原理(一)

之前的 Runloop原理(一) 中测试是在主线程进行的,接下来在子线程中进行

以下涉及的内容均是针对子线程的

Starting the Run Loop

只有在子线程中启动runloop 才是必要的

runloop必须至少有一个inpurt source 或者 timer,如果一个也没有,则runloop 马上退出

启动runloop有几种方式

  • Unconditionally

    无条件进入runloop是最简单的选择,但也是最不可取的;

    无条件地运行runloop会使线程进入永久循环,这使得你对runloop本身几乎没有控制权

    你可以添加和删除input sources和timer,但唯一能停止runloop的方法是终止它,也没有办法在custom mode中运行runloop

  • With a set time limit

    设定限制时间

    如果设定超时,runloop将一直运行直到事件到达或者分配的时间过期为止

  • In a particular mode

    在特定mode下

线程主入口框架版本

image.png

子线程中 没有启动runloop,timer是没办法调度执行的,而且子线程一启动,马上就销毁了

image.png

无条件启动runloop,timer调度执行, 而且直接run runloop,后面的代码执行阻塞

此时 主动让线程exit, timer也停止,说明timer调度是依托于runloop的

runloop添加非基于port的input source

image.png

对于非基于port的input source,runloop休眠,监视source的signal事件,如果没有其他线程对source的signal,runloop将超时 退出

也就是

image.png

runloop通过Core Foundation添加timer

image.png

runloop启动之后有超时,图中设置了10秒超时

虽然timer每5秒触发一次,但timer却是基于runloop调度的

过10秒之后 runloop超时 退出,因为采用了while,所以runloop退出之后又重新启动

添加timer - 直观演示runloop流程序列

为了更直观的了解timer究竟是如何调度的,这里再总结一次

  • 首先开启一个子线程
image.png
  • runloop 注册observer
image.png
  • observer通知回调
image.png
  • runloop 添加timer
image.png
  • timer 任务
image.png
  • 添加source (非基于port)
image.png
  • source注册回调函数
image.png
  • 控制台结果打印 -------
image.png

关于timer的流程打印总结说明

  • 首先进入runloop (配置的启动方式为非阻塞的,超时会退出)

  • 发现有timer,通知observer即将处理timer任务调度

    但是timer的任务调度是按照计划设置的时间表来执行的,进入runloop第一件事是先检查是否配置了timer计划

    有计划不代表runloop马上要调度timer任务去执行,而是看当前的时间是否到了计划的执行时间,如果时间到了,就调度task执行,如果没到,心里有数,继续下一项议题 source

  • 发现有source,通知observer即将处理source

    source的执行需要有signal,没有signal什么也不做

    跟timer类似,就是runloop调度计划表里有source,但是调度执行需要一个契机, 这个契机就是signal

  • 接下来通知observer即将休眠

  • 当前时间如果符合 timer计划表里的时间点,唤醒runloop, runloop 通知observer唤醒

    唤醒发生在timer调度任务执行之前

  • 执行timer任务

  • 如果此时runloop 10秒超时未过期,将重新启动循环, 即将进入timer开始

    • 继续一轮循环 即将进入timer -> 即将处理source -> 休眠 -> timer唤醒 -> 马上退出
  • 如果此时runloop 10秒超时过期,runloop退出

source的执行是怎么样的

signal + wakeup

image.png

touch 一下

image.png

touch之后,runloop唤醒,此时你会发现,即将进入source之后 --> 执行source --> 退出 --> 进入runloop

唤醒runloop,循环轮询一次,source执行之后,会马上退出。之所以这样,是因为touch显式唤醒runloop会重新启动runloop

退出runloop

有两种方式退出tunloop

  • runloop设置超时

  • 告诉runloop stop --- CFRunLoopStop

虽然移除 input sources 和 timers可以引起runloop退出,但这是不可靠的. 一些系统例程将input sources添加到runloop中以处理所需的事件, 你的代码可能不知道这些input sources,所以无法删除它们,这将阻止runloop退出

线程安全和runloop对象

线程安全取决于你使用哪种api操作runloop

  • Core Foundation里的方法通常是线程安全的,可以在任何线程里调用

  • Cocoa NSRunLoop类不像Core Foundation对应类那样天生安全

    如果你使用NSRunLoop修改runloop,你只能在此runloop的线程里操作

    在线程里往runloop里添加input source 和timer,但是runloop属于其他线程, 就会崩溃

相关文章

  • [iOS] 底层原理二 (Runtime、Runloop)

    底层原理一:(OC本质、KVC、KVO、Categroy、Block)底层原理二:(Runtime、Runloop...

  • [iOS] 底层原理五 (面试题目整理)

    底层原理一:(OC本质、KVC、KVO、Categroy、Block)底层原理二:(Runtime、Runloop...

  • Runloop原理(二)

    Runloop原理(一)[https://www.jianshu.com/p/b89633d280d1] 之前的 ...

  • runloop

    runloop是什么 runloop与线程有什么关系 runloop的原理 runloop的使用

  • RunLoop简介

    RunLoop简介 RunLoop底层实现原理 RunLoop接收输入事件的2种来源 RunLoop对象 开源的C...

  • iOS RunLoop应用分析—原来这些都在使用RunLoop

    之前已经介绍过RunLoop原理,感兴趣的同学可以阅读iOS——解密RunLoop原理[https://xiaoz...

  • RunLoop研究

    目录: App启动原理 RunLoop 的概念 RunLoop 与线程的关系 RunLoop 对外的接口 RunL...

  • Runloop

    Runloop 实现原理及应用iOS - RunLoop 底层源码详解及具体运用

  • RunLoop的概念及作用

    1.RunLoop的概念及作用 2.RunLoop的使用 3.RunLoop的相关类 4.RunLoop的工作原理...

  • RunLoop

    1.RunLoop的概念及作用 2.RunLoop的使用 3.RunLoop的相关类 4.RunLoop的工作原理...

网友评论

    本文标题:Runloop原理(二)

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