NSTimer,NSTask,NSThread和NSRunloop之间的基本区别是什么?

NSTimerNSTaskNSThreadNSRunloop之间有什么区别,有什么时候使用它们的指导原则?

每个程序至less运行一个线程 。 您可以将每个线程看作是一个独立的程序执行过程,每个过程与其他过程并行。

如果您有某种用户界面或需要监听事件的其他代码(如networking端口),则需要运行循环 。 每个NSThread自动获得自己的运行循环,而且你很less直接关心它们。 运行循环也负责创build和释放自动释放池。

[编辑:请参阅评论关于autorelease池的更多讨论。 要记住的最重要的一点是,新线程必须注意build立一个自动释放池。 例如,使用detachNewThreadSelector(见下文)调用的方法应该包含以下内容作为它们的第一行和最后一行:

  NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ]; [code here] [pool release]; 

这同样适用于使用其他技术产生的线程。]

在所有UI处理发生的主线程中 ,运行循环非常重要,因为它使接口保持反应。 这就是为什么你永远不应该在主线程中运行耗时的代码:它会占用线程的所有时间,并且运行循环不会被允许运行得足够频繁,导致一个locking或者缓慢的接口。 如果您需要执行耗时的计算,或者使任务在后台运行,则应该创build一个新线程。 同样,您可能不必考虑正在创build的新运行循环。 在新线程中执行方法的简单方法:

 [NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil]; 

线程之间的通信可能会非常棘手,您应该了解方法performSelector:onThread:withObject:waitUntilDone:performSelectorOnMainThread:withObject:waitUntilDone:在这里跨线程发送NSNotifications的重要提示。

定时器也由运行循环处理。 与运行循环相反,您可能经常直接在您的程序中使用计时器。 创build计时器最简单的方法是:

 [self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0]; 

但是有时你想自己创build和pipe理NSTimer对象,例如能够取消并重新使用计时器。

一个NSTask被用来运行另一个程序作为当前的一个子进程 。 这有点类似于启动一个单独的线程,但如果一个subprocess崩溃,你的主程序将继续运行。 程序之间的通信也与同一进程中多个线程之间的通信非常不同。

你用“iphone”标记了你的问题,而在iPhone上你永远不会使用NSTasks。

NSOperations用于处理大量不同的任务,将它们放入队列中和/或在单独的线程中处理它们(尽pipe它们不必在单独的线程中运行)。 如果您的应用程序需要创build一些专用的线程,那么没有理由使用NSOperation类。 但是,如果你经常会产生一些必须跟踪的任务(比如与服务器通信),那么NSOperation和NSOperationQueue就会派上用场。

  • NSTimer是一个计时器对象,是将来在对象上调用select器的一种方法。
  • NSThread是一个线程类。 我想你知道一个线程是什么。
  • NSTask是一个进程类,是从程序运行另一个程序的一种方式。
  • NSOperation (我添加到这个问题)是一个单一的任务非常好的抽象。 你在这个类中embedded你的操作,你可以很容易地通过一个NSOperationQueue类同时执行。
  • NSRunLoop是最难理解的。 以某种方式抽象和调整select() unix系统调用,pipe理input源以及调度线程上的事件和定时器。

指南是Apple Threading编程指南 。

其他答案在总结定时器,任务和线程方面做得相当不错。 我想对NSRunloop进行更多的评论,因为我认为大部分的其他答案在这里仍然有些混乱。 从NSRunloop文档:

NSRunLoop对象处理来自窗口系统的鼠标和键盘事件,NSPort对象和NSConnection对象的input。 一个NSRunLoop对象也处理NSTimer事件。

通常,您的应用程序不需要创build或显式pipe理NSRunLoop对象。 每个NSThread对象(包括应用程序的主线程)都根据需要自动创build一个NSRunLoop对象。 如果您需要访问当前线程的运行循环,则可以使用类方法currentRunLoop进行操作。

将NSRunloop看作是特定线程的主要事件处理和调度循环。 它从input设备读取,为需要服务的任何对象提供服务,并适当地分派数据。