1.线程与runloop的关系
原文地址1:http://blog.csdn.net/wzzvictory/article/details/9237973
原文地址2:http://blog.ibireme.com(本文还没有写,未完待续)
原文写的很详细,需要深入了解的请参考原文。此处我只是做一些归纳总结,日后翻阅的时候大致有一些思路。
一、线程与Runloop的关系
1.线程与runloop密切相关
1)run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。
2)Run loops是线程的基础架构部分,Cocoa和CoreFundation都提供了run loop对象方便配置和管理线程的run loop。每个线程,包括程序的主线程(main thread)都有与之相应的run loop对象。
2.几点说明
1)主线程runloop默认启动:UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象
int main(int argc,char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([appDelegate class]));
}
}
2)对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
3.获取当前线程:
NSRunLoop *runloop = [NSRunLoopcurrentRunLoop];
4.runloop也负责autorelease pool的创建和释放
典型例子:读入大量图像的同时改变它的尺寸。图像文件读入到NSData对象,并从中生成UIImage对象。改变对象尺寸后又生成 新的UIImage,此时就会产生大量autorelease的对象。
for(int i=0; i<图像数量; i++){
//如上操作
}
这时候,有必要在适当的地方生成、持有或者废弃NSAutorelease对象
for(int i=0; i<图像数量; i++){
//如上操作
[pool drain]; //进行一次释放
}
总结一:
一个run loop就是一个事件处理循环,用来不停的监听和处理输入事件并将其分配到对应的目标上进行处理。如果仅仅是想实现这个功能,你可能会想一个简单的while循环不就可以实现了吗,用得着费老大劲来做个那么复杂的机制?显然,苹果的架构设计师不是吃干饭的,你想到的他们早就想过了。
1)首先,NSRunLoop是一种更加高明的消息处理模式,他就高明在对消息处理过程进行了更好的抽象和封装,这样才能是的你不用处理一些很琐碎很低层次的具体消息的处理,在NSRunLoop中每一个消息就被打包在input source或者是timer source(见后文)中了。
2)important:使用run loop可以使你的线程在有工作的时候工作,没有工作的时候休眠,这可以大大节省系统资源。
二:Runloop的深入了解(笔者对这部分内容使用不多,不深入讲解。请参考转载原文)
1.runloop接收输入事件:
①输入源:
1)当你创建输入源,你需要将其分配给run loop中的一个或多个模式(什么是模式,下文将会讲到)。模式只会在特定事件影响监听的源。大多数情况下,run loop运行在默认模式下,但是你也可以使其运行在自定义模式。若某一源在当前模式下不被监听,那么任何其生成的消息只在run loop运行在其关联的模式下才会被传递。
2)传递异步事件,通常消息来自于其他线程或程序。输入源传递异步消息给相应的处理例程,并调用runUntilDate:方法来退出(在线程里面相关的NSRunLoop对象调用)。
②定时源:
1)需要注意的是,尽管定时器可以产生基于时间的通知,但它并不是实时机制。和输入源一样,定时器也和你的run loop的特定模式相关。如果定时器所在的模式当前未被run loop监视,那么定时器将不会开始直到run loop运行在相应的模式下。类似的,如果定时器在run loop处理某一事件期间开始,定时器会一直等待直到下次run loop开始相应的处理程序。如果run loop不再运行,那定时器也将永远不启动。
2)定时源在预设的时间点同步方式传递消息,这些消息都会发生在特定时间或者重复的时间间隔。定时源则直接传递消息给处理例程,不会立即退出run loop。
三、什么时候使用runloop
1)仅当在为你的程序创建辅助线程的时候,你才需要显式运行一个run loop
2)Run loop是程序主线程基础设施的关键部分。所以,Cocoa和Carbon程序提供了代码运行主程序的循环并自动启动run loop。IOS程序中UIApplication的run方法(或Mac OS X中的NSApplication)作为程序启动步骤的一部分,它在程序正常启动的时候就会启动程序的主循环。
3)对于辅助线程,你需要判断一个run loop是否是必须的。如果是必须的,那么你要自己配置并启动它。你不需要在任何情况下都去启动一个线程的run loop。比如,你使用线程来处理一个预先定义的长时间运行的任务时,你应该避免启动run loop。Run loop在你要和线程有更多的交互时才需要,比如以下情况:
使用端口或自定义输入源来和其他线程通信
使用线程的定时器
Cocoa中使用任何performSelector…的方法
使线程周期性工作
4)如果你决定在程序中使用run loop,那么它的配置和启动都很简单。和所有线程编程一样,你需要计划好在辅助线程退出线程的情形。让线程自然退出往往比强制关闭它更好。
四、runloop的model:
model 主要是用来指定事件在运行循环中的优先级的,分为:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
UITrackingRunLoopMode:ScrollView滑动时
UIInitializationRunLoopMode:启动时
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
苹果公开提供的 Mode 有两个:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)