美文网首页
IOS基础知识-Runloop原理篇

IOS基础知识-Runloop原理篇

作者: 程序员的自我救赎 | 来源:发表于2019-06-26 10:33 被阅读0次

    1、讲讲 RunLoop,项目中有用到吗?
    2、RunLoop内部实现逻辑?
    3、Runloop和线程的关系?
    4、timer 与 Runloop 的关系?
    5、程序中添加每3秒响应一次的NSTimer,当拖动tableview时timer可能无法响应要怎么解决?
    6、Runloop 是怎么响应用户操作的, 具体流程是什么样的?
    7、说说RunLoop的几种状态?
    8、Runloop的mode作用是什么?

    Runloop:运行循环,在程序运行过程中循环做一些事情,如果没有Runloop程序执行完毕就会立即退出,如果有Runloop程序会一直运行,并且时时刻刻在等待用户的输入操作。RunLoop可以在需要的时候自己跑起来运行,在没有操作的时候就停下来休息。充分节省CPU资源,提高程序性能。

    Runloop的基本作用:

    a、保持程序持续运行,程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行
    b、处理App中的各种事件(比如:触摸事件,定时器事件,Selector事件等)
    c、节省CPU资源,提高程序性能,
    

    RunLoop在哪里开启?

    UIApplicationMain函数内启动了Runloop,程序不会马上退出,而是保持运行状态。因此每一个应用必须要有一个runloop,
    我们知道主线程一开起来,就会跑一个和主线程对应的RunLoop,那么RunLoop一定是在程序的入口main函数中开启。
    

    如何获得RunLoop对象

    Foundation
    [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
    [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
    
    Core Foundation
    CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
    CFRunLoopGetMain(); // 获得主线程的RunLoop对象
    

    RunLoop和线程间的关系

    a、每条线程都有唯一的一个与之对应的RunLoop对象
    b、RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value
    c、主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建
    d、RunLoop在第一次获取时创建,在线程结束时销毁
    

    RunLoop结构体包含哪些?

    Source1 : 基于Port的线程间通信
    Source0 : 触摸事件,PerformSelectors
    Timers : 定时器
    Observer : 监听器,用于监听RunLoop的状态
    

    RunLoop处理逻辑流程图


    1434508-d448ec1fc5171e09.png

    RunLoop退出

    主线程销毁RunLoop退出
    Mode中有一些Timer 、Source、 Observer,这些保证Mode不为空时保证RunLoop没有空转并且是在运行的,当Mode中为空的时候,RunLoop会立刻退出
    我们在启动RunLoop的时候可以设置什么时候停止

    RunLoop应用

    1. 常驻线程
      常驻线程的作用:我们知道,当子线程中的任务执行完毕之后就被销毁了,那么如果我们需要开启一个子线程,在程序运行过程中永远都存在,那么我们就会面临一个问题,如何让子线程永远活着,这时就要用到常驻线程:给子线程开启一个RunLoop
      注意:子线程执行完操作之后就会立即释放,即使我们使用强引用引用子线程使子线程不被释放,也不能给子线程再次添加操作,或者再次开启。
      子线程开启RunLoop的代码,先点击屏幕开启子线程并开启子线程RunLoop,然后点击button。
      创建子线程相关的RunLoop,在子线程中创建即可,并且RunLoop中要至少有一个Timer 或 一个Source 保证RunLoop不会因为空转而退出,因此在创建的时候直接加入,如果没有加入Timer或者Source,或者只加入一个监听者,运行程序会崩溃

    自动释放池
    Timer和Source也是一些变量,需要占用一部分存储空间,所以要释放掉,如果不释放掉,就会一直积累,占用的内存也就越来越大,这显然不是我们想要的。
    那么什么时候释放,怎么释放呢?
    RunLoop内部有一个自动释放池,当RunLoop开启时,就会自动创建一个自动释放池,当RunLoop在休息之前会释放掉自动释放池的东西,然后重新创建一个新的空的自动释放池,当RunLoop被唤醒重新开始跑圈时,Timer,Source等新的事件就会放到新的自动释放池中,当RunLoop退出的时候也会被释放。
    注意:只有主线程的RunLoop会默认启动。也就意味着会自动创建自动释放池,子线程需要在线程调度方法中手动添加自动释放池。

    相关文章

      网友评论

          本文标题:IOS基础知识-Runloop原理篇

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