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应用
- 常驻线程
常驻线程的作用:我们知道,当子线程中的任务执行完毕之后就被销毁了,那么如果我们需要开启一个子线程,在程序运行过程中永远都存在,那么我们就会面临一个问题,如何让子线程永远活着,这时就要用到常驻线程:给子线程开启一个RunLoop
注意:子线程执行完操作之后就会立即释放,即使我们使用强引用引用子线程使子线程不被释放,也不能给子线程再次添加操作,或者再次开启。
子线程开启RunLoop的代码,先点击屏幕开启子线程并开启子线程RunLoop,然后点击button。
创建子线程相关的RunLoop,在子线程中创建即可,并且RunLoop中要至少有一个Timer 或 一个Source 保证RunLoop不会因为空转而退出,因此在创建的时候直接加入,如果没有加入Timer或者Source,或者只加入一个监听者,运行程序会崩溃
自动释放池
Timer和Source也是一些变量,需要占用一部分存储空间,所以要释放掉,如果不释放掉,就会一直积累,占用的内存也就越来越大,这显然不是我们想要的。
那么什么时候释放,怎么释放呢?
RunLoop内部有一个自动释放池,当RunLoop开启时,就会自动创建一个自动释放池,当RunLoop在休息之前会释放掉自动释放池的东西,然后重新创建一个新的空的自动释放池,当RunLoop被唤醒重新开始跑圈时,Timer,Source等新的事件就会放到新的自动释放池中,当RunLoop退出的时候也会被释放。
注意:只有主线程的RunLoop会默认启动。也就意味着会自动创建自动释放池,子线程需要在线程调度方法中手动添加自动释放池。
网友评论