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

时间:2009-07-14 08:44:46

标签: iphone ios multithreading cocoa

NSTimerNSTaskNSThreadNSRunloop之间有什么区别,是否有关于何时使用这些内容的指南?

3 个答案:

答案 0 :(得分:43)

每个程序至少运行一个线程。您可以将每个线程视为一个独立的程序执行过程,每个过程都与其他线程并行运行。

如果您有某种用户界面或需要侦听事件的其他代码(如网络端口),则需要运行循环。每个NSThread都会自动获得自己的运行循环,而您很少需要直接关注它们。运行循环还负责创建和释放自动释放池。

[编辑:有关自动释放池的更多讨论,请参阅注释。要记住的最重要的一点是新线程必须注意设置自动释放池。例如,使用detachNewThreadSelector调用的方法(见下文)应该包含以下第一行和最后一行:

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

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

在所有UI处理正在进行的主线程中,运行循环非常重要,因为它使接口保持活动状态。这就是为什么你永远不应该在主线程上运行耗时的代码:它会在线程上耗尽所有时间并且不允许运行循环经常运行,从而导致锁定或慢速接口。如果您需要执行耗时的计算,或者让任务在后台运行,您应该创建一个新线程。同样,您可能不必考虑正在创建的新运行循环。在新线程中执行方法的简便方法:

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

线程间通信可能很棘手,您应该了解方法performSelector:onThread:withObject:waitUntilDone:performSelectorOnMainThread:withObject:waitUntilDone: (跨线程here发送NSNotification的重要提示。)

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

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

但有时你想自己创建和管理NSTimer对象,例如能够取消和重复使用计时器。

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

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

当您需要处理大量不同的任务,将它们放入队列和/或在单独的线程中处理它们时,会使用

NSOperations (尽管它们没有 >在不同的线程中运行)。如果您的应用程序需要只创建一些专用线程,那么就没有理由使用NSOperation类。但是,如果您经常生成必须跟踪的任务(如与服务器通信),NSOperation和NSOperationQueue将会派上用场。

答案 1 :(得分:4)

  • NSTimer是一个计时器对象,是将来在对象上调用选择器的一种方法。
  • NSThread是一个线程类。我想你知道什么是线程。
  • NSTask是一个进程类,一种从程序中运行另一个程序的方法。
  • NSOperation(我正在添加问题)对于单个任务来说是一个非常好的抽象。您将操作嵌入此类中,并且可以通过NSOperationQueue类轻松地同时执行。
  • NSRunLoop是最难理解的。在某种程度上抽象并调整select() unix系统调用,管理输入源以及在线程上调度事件和计时器。

指南是Apple Threading Programming Guide

答案 2 :(得分:3)

其他答案在总结计时器,任务和线程方面做得非常好。我想对NSRunloop进行更多评论,因为我认为其他大多数答案仍然存在一些混乱。来自NSRunloop文档:

  

NSRunLoop对象处理输入   用于鼠标和键盘等来源   来自窗口系统的事件,NSPort   对象和NSConnection对象。一个   NSRunLoop对象也处理   NSTimer活动。

  

一般情况下,您的应用程序没有   需要创建或显式   管理NSRunLoop对象。每   NSThread对象,包括   应用程序的主线程,有一个   NSRunLoop对象自动创建   根据需要。如果你需要   访问当前线程的运行循环,   你用类方法这样做   currentRunLoop。

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