这是一道可能经常被问的面试题,首先先说一下NSRunloop。
- NSRunloop是一个消息循环,会监测输入源(inputsource)和定时源(timer source)。apple官方文档(多线程编程指南)描述: "run loop 是用来在线程上管理事件异步到达的基础设施......run loop在没有任何事件处理的时候会把它的线程置于休眠状态,它消除了消耗CPU周期轮询,并防止处理器本身进入休眠状态并节省电源。"消除CPU空转是它最大的作用。
Runloop的重点是:
1.用来监听长耗时异步事件,例如网络回调,苹果原生和第三方用的都是Runloop。
2.消除CPU空转。 - 每个线程都有一个默认的NSRunloop,主线程中的NSRunloop默认是运行的,非主线程中的NSRunloop默认是没有运行的,通常需要为NSRunloop添加一个事件然后去运行。一般情况下没有必要去启动一个线程的NSRunloop,除非需要长久的去监测某个异步事件。举个具体的例子,NSURLConnection网络数据请求,默认是异步的方式,其创建原理就是创建之后将其作为事件源加入当前的Runloop,而等待网络响应的过程是在一个新建的独立的线程中完成,当这个线程处理到某个阶段比如收到响应后便通知之前的线程去执行相应的delegate方法。
下面说说Runloop与autorelease的关系
- 对于每一个runloop,Entry事件(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池,这样所有的AutoreleasePool会构成一个像CallStact一样的栈式结构,在每一个Runloop结束时,Exit(即将退出Loop)调用_objc_autoreleasePoolPop() ,当前栈顶的AutoreleasePool会被销毁,这样这个Pool里面的每个object都有被release。