Runloop原理(二)

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下

线程主入口框架版本

在这里插入图片描述

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

在这里插入图片描述

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

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

runloop添加非基于port的input source

在这里插入图片描述

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

也就是

在这里插入图片描述

runloop通过Core Foundation添加timer

在这里插入图片描述

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

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

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

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

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

  • 首先开启一个子线程

在这里插入图片描述

  • runloop注册observer

在这里插入图片描述

  • observer通知回调

在这里插入图片描述

  • runloop 添加timer

在这里插入图片描述

  • timer任务

在这里插入图片描述

  • 添加source (非基于port)

在这里插入图片描述

  • source注册回调函数

在这里插入图片描述

  • 控制台结果打印 -------

在这里插入图片描述

关于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

在这里插入图片描述

touch 一下

在这里插入图片描述

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属于其他线程, 就会崩溃

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值