每个程序至少运行于一个thread中(称为main thread),你可以认为每个thread是一个独立的处理器,每个都并行的运行着。Thread是用来为在同一个进程中并行的执行多处代码。
如果你的应用程序只有一个thread,则这个thread需要完成这个应用的所有事情。它必需对事件进行响应,更新应用程序窗口以及完成应用结果的所有运算。这样的话问题就来了,只有一个thread且它同一时间只能做一件事,如果你的应用程序有一个运算需要很长的时间那会发生什么呢?你的代码在忙于运算其需要的结果,你的应用程序则停止了对用户事件响应和更新窗口。如果这个运算进行了很长时间,则用户可能会认为应用程序已失去了响应并将其关闭。如果你将运算移到另一个thread中,则main thread则只用于事件响应和更新窗口。这就是为什么不应该在main thread中运行有时间持续消耗(堵塞)的代码。
一个在新thread中运行函数的方法:
- [NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil];
如果你有一些用户界面或者其它的代码需要对事件进行监听(如网络接口),你则要使用到run loop。每个thread会创建其自己的run loop,通常我们并不需要关心这些。Run loop同时也负责autorelease pool的创建和释放。
对于每个新建的thread都需要为其创建一个autorelease pool,如果有一个方法调用detachNewThreadSelector,则需要使用如下的autorelease pool相应的代码将其包含在内:
Run loop(CFRunLoop)是一个事件处理循环,你可以用来安排工作并协调你所收到的事件。使用run loop的目的是保持你的thread当有事件处理时处于忙状态并当没有事件处理时进入休眠。
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [code here]
- [pool release];
Run loop是一组架构用来管理thread中收到的异步消息。Run loop运行时对thread中的一个或多个事件源进行监控。当事件到达时,系统将thread唤醒并将事件发送给run loop,然后run loop将事件再次转发给你所指定的处理函数。如果没有收到事件或事件处理完成后,run loop将thread设置为休眠。你可以不为你所创建的thread设置run loop,但设置了将为用户提供很好的体验。Run loop为创建长时间运行且消耗少量资源的thread提供了可能。因为run loop将其所属thread设置为休眠状态如果没有事件收到。要对run loop进行配置,你所要做的是创建你的thread,获得对run loop对象的引用,安装你的事件处理器并运行run loop。Cocoa为你在main thread中自动配置了run loop,如果你要创建另一个长时间运行的thread,则你必须自己对run loop进行配置。
Run loop就像它的名字一样,是你thread中的一个循环并对收到的事件进行处理。你的代码提供控制语句用来对run loop进行执行——换句话说:你的代码提供while或for循环来驱动run loop。在你的循环中,你使用run loop对象来“运行”事件处理代码。事件处理代码主要进行接收事件并调用事件处理函数。
Run loop从两个不同的事件源中接收消息。Input sources(CFRunLoopSource)投递异步消息,通常来自于另一个thread或另一个应用程序。Timer sources(CFRunLoopTimer)当在计划的时间或重复的时间间隔内投递同步消息。两种事件源都使用应用程序指定的处理方式对到达的事件进行处理。下图展示了run loop和不同的事件源结构。
Input sources投递异步消息至对应的处理器并导致退出runUnitDate:方法(该方法在将run loop与thread关联时调用)的执行。Timer sources投递同步消息至对应的处理器但并不导致run loop退出。为了能对input sources进行额外处理,run loops也能根据run loop的行为产生相应的通知。注册run loop observers(CFRunLoopObserver)可以接收到这些通知并使用它们在thread上进行额外的处理。
你的应用程序不需要创建或显示的管理NSRunLoop对象。每一个NSThread对象,包括应用程序的main Thread都会自动创建一个NSRunLoop对象。如果你需要访问当前thread的run loop,你可以使用NSRunLoop对象的类方法currentRunLoop。
Timer(定时器)也是通过run loop进行处理。与run loop进行比较,你通常在你的程序中直接使用Timer。
创建一个timer的最简单方法:
有些情况下你也可能创建自己的NSTimer对象,从而可以自己对Timer进行释放和重用。
- [self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0];