原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
我的stackoverflow
前言:Runloop多线程开发的中的一个概念,当然也可以向Runloop中提交一些任务,监听一些事件。属于多线程编程的一部分,合理的使用Runloop对App的性能提高有很大帮助。
关于Runloop 的官方资料
笔者也是主要从三个链接中理解和概括的,如果英文好的同学,同时觉得自己对Runloop的理解不够,还是建议自习读读官方的文档,那是最权威的东西。
什么是Runloop
Runloop是为了让线程高效处理任务而创建的机制。一个Runloop就是一个事件处理循环(Event processing loop),通过Runloop可以执行一些计划任务,接受一些事件。Runloop的特点是能够在有任务的时候让线程被唤醒,而没有任务的时候线程休眠
Runloop与线程的关系
在iOS开发中,每个线程(NSThread)在创建的时候都会自动绑定一个Runloop。主线程的Runloop在App启动的时候自动运行。自己创建的线程,要写代码来启动Runloop,提交任务,接受事件。
RunLoop的运行机制
Runloop和它的名字很像,他就是线程运行的一个循环,通过这个循环可以处理事件回调。Runloop从两个源头接收事件
从input sources接收异步事件,来源通常是从其其它线程或者其他应用
从Timer sources接收同步事件,这种事件是在指定时间触发的
除了提供回调之外,Runloop还能触发一些Notification来告诉观察者当前Runloop处于的状态。
我们再来看看iOS中,与Runloop相关的数据类型
NSRunLoop ,面相对象的方式处理Runloop,非线程安全
CFRunLoop ,C相关的关于Runloop的函数,线程安全
CFRunLoopSource,一种抽象的表示input source的对象,这种对象可以被加入到Runloop中,并且产生异步回调。例如网络数据到达,或者用户操作。CFRunLoopSource一共有两种类型,Version 0 Source 和Version 1 Source。(之所以这样命名,是因为其内部实现的有个version字段对应的是0/1)
- Version 0 Source,这种source要应用自己管理,当这种source触发的时候,需要程序手动调用CFRunLoopSourceSignal 来触发。CFSocket就是这种Source。
- Version1 Source,这种Source由内核和Runloop自动管理。当这种Source能够触发的时候,使用Mach ports 来通知Source。也就是说,当Mach ports 接收到可以触发的消息时候,内核自动触发这种Source
简单理解,由应用发起的任务就是Version 0,其余是Source 1
CFRunLoopTimer,是一种特别得Source,在将来的某一时间点触发。注意,这个timer的触发事件并不是精确的。当Timer所处的Mode并没有在运行,或者一个长时间的回调在执行。Timer会延迟到下一个Runloop再判断是否要触发。CFRunLoopTimer与NSTimer是toll-free bridged,意味着传入NSTimer *的地方就可以传入CFRunLoopTimerRef
CFRunLoopObserver,通过CFRunLoopObserver可以监听Runloop执行过程中的不同状态。例如开始一个Loop,结束一个Loop等。
Runloop Mode
Runloop Mode可以理解为运行模式,每个运行模式中包含了input sources和time sources以及observers,Runloop可以在多个运行模式中切换。只有处于Runloop当前模式中的timer,sources以及observers才是有效的。
通过模式切换,可以过滤掉不想要的事件,有选择的处理任务,使得各种mode相互不影响。比如主线程的Runloop就有两个模式kCFRunLoopDefaultMode和UITrackingRunLoopMode。其中,默认是运行在kCFRunLoopDefaultMode。在监听用户持续触摸的时候会切换到UITrackingRunLoopMode。所以,在Scrollview滚动的时候,添加的timer会失效,来保证滚动的流畅性。
Mode分为两种,Core Foundation预置的有几种,当然也可以自己通过CFRunloop相关API创建Mode,不同Mode按照name来区分。
预定义的几种Mode
- kCFRunLoopDefaultMode 默认的模式,大多数情况下都适用默认模式
- UITrackingRunLoopMode,接收到用户的持续触摸时候切换到的模式。
- kCFRunLoopCommonModes ,common mode,当像common mode中添加input source时候,也会像在标注为common mode的其他添加。(注意,不包括observer以及timer)
input Source
实际开发中常用的提交Source的是这一组列代码。这一组代码提交的Source是序列化的提交到一个线程上的,解决了很多在一个线程上执行多任务的问题。在执行完后,source会自动释放,使用这一组代码,可以向任何线程传递消息
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:
performSelector:onThread:withObject:waitUntilDone