在不同的线程上调用我的方法有哪些不同的方法?

我有一些数据计算方法(让它是“myMethod:”),我想移动到另一个线程的调用,因为我不想阻止我的主要用户界面function。 所以,开始做一些关于如何在另一个线程上调用我的方法的研究。 据我所知,目前有很多不同的方法来做到这一点。 这是一个列表:

a)使用纯线程(可用于iOS 2.0):

[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray]; 

b)使用简单的快捷方式(从iOS 2.0开始可用)。 可用于inheritance的NSObject,但该方法也属于NSThread类:

 [self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray]; 

c)使用Grand Central Dispatch队列的新方法(从iOS 4.0开始):

 dispatch_async(dispatch_get_global_queue(0, 0), ^ { [self myMethod:_myParamsArray]; }); 

d)不知何故,使用一些类,如NSOperation,NSBlockOperation或NSOperationQueue,虽然不知道该怎么做(一些例子,将不胜感激)

目前,我曾经用过“b”这个案例,但是对这个利弊感兴趣,还有其他相关的build议。

更新:e)也发现了另一种执行类似线程的东西 – 运行循环 。 以下是苹果文档摘录:

运行循环是一个事件处理循环,用于安排工作和协调收到的事件。 运行循环的目的是在有工作要做的时候保持你的线程忙,当没有时候让线程进入睡眠状态。

恕我直言,或多或less你正在处理相同的任务 – 如何调用你的方法在单独的线程进行asynchronous操作。

更新2:已经有了NSInvocationOperation和NSOperationQueue和恕我直言的一些经验,这是相当方便的。 根据苹果文档,GCD和NSOperations是实现multithreading的首选方式。 而且,NSOperations从iOS 4.0开始运行在GCD上。 简而言之,你实例化NSIvocationOperation(作为你的方法的调用),然后实例化NSOperationQueue并将调用添加到队列中。 NSOperationQueue足够聪明,你可以将多个NSIvocationOperation对象(包装你的方法调用)和它们实例化到NSOperationQueue。 剩下的就放心了。 NSOperationQueue确定需要多less个并行线程来执行调用(NSInvocationOperation)并为您处理。 它可以在线程A上执行第一个调用,然后在线程B上执行第一个调用,在线程C上执行第三个,然后执行在线程B上,所以你不必担心这个问题。 但是,如果你想,你可以告诉NSOperationQueue最大的线程可以用来执行调用(例如1),但我没有这个需要。 默认情况下,所有的任务都是在主线程以外的地方执行的,所以操作队列默认是asynchronous的。 另外,如果你想在一个严格队列中执行你的方法调用(每个包装在单独的NSInvocationOperation中),那么你可以添加依赖关系,所以NSOperationQueue将保留方法调用顺序。 这是一个例子:

 // wrap your method call into NSInvocationOperation object NSInvocationOperation *currentOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(yourMethodCall) object:nil]; // _sharedOperationQueue is a shared NSOperationQueue // get all executing operations from the queue and get the last operation _lastOperation = [[_sharedOperationQueue operations] lastObject]; // check if _lastOperation is not nil if (_lastOperation) { // if not then add dependency, so the calls would be performed in a queue [currentOperation addDependency:_lastOperation]; } // say - execute my method (operation) [_sharedOperationQueue addOperation:currentOperation]; _lastOperation = currentOperation; // mark as last operation for adding dependency to the next operation // the queue will retain invocation operation so you will release [currentOperation release]; ..... you can create another NSInvocationOperation and add it to the queue.... 

至于RUNLOOP,仍然有时你会面对它们,例如当启动/计划一个计时器,或者build立NSURL连接时。 恕我直言,一个runloop可能会比较一个线程上执行的任务队列。 恕我直言,runloop是指向作为队列运行的线程的指针:它具有可能抛出事件的任务,并且将被放置在该线程队列的末尾。 默认情况下,应用程序中的所有任务都在单个线程中运行。 我说这是一个指针,因为当你的应用程序生成事件时,应用程序必须知道该事件(touch事件或其他委托callback)的执行位置。 当然,你应该阅读runloops的更详细的信息,因为这些只是我的想法。

通常情况下,你会更喜欢GCD方法。

谈到同步/locking比纯线程(NSThread – pthread)更简单,从性能angular度来看可能更准确。

使用纯线程时,问题是您可能会遇到性能问题,具体取决于可用内核/处理器的数量。

例如,如果你只有一个内核,创build许multithreading可能会减慢你的应用程序,因为CPU将把大部分时间从一个线程切换到另一个线程,从而保存堆栈,寄存器等。

另一方面,如果你有很多可用的内核,创build很多不同的线程可能会很好。

这是GCD帮助的地方,因为它为您pipe理。 它将根据可用的系统资源创build适当数量的线程,以保证最佳利用率,并适当地调度您的操作。

但是,由于这个原因,使用GCD发起的任务可能不是实时的。

所以,如果你真的需要一个分离的任务立即运行,使用明确的线程。 否则,使用GCD。

希望对你有帮助 : )

编辑

有关performSelectorInBackground的注释:它只是创build一个新的线程。 所以与NSThread方法基本上没有区别。

编辑2

NSOperation相关的东西有点不同。 在Mac OS X上,它们是从版本10.6开始使用GCD实现的。 以前的版本使用线程。

在iOS上,它们仅使用线程来实现。

参考

所有这些在“ 并发编程指南”中都有很好的解释。 它讨论了GCD和线程方法,以及有关使用和实现的大量细节。

如果你还没有阅读,你应该看看。