NSOperation vs中央调度

我正在学习iOS的并发编程。到目前为止,我已经阅读了__ABC0 / NSOperationQueueGCD使用__ABC1而不是GCD的原因是什么,反之亦然?

听起来好像GCDNSOperationQueue都从用户那里抽象出了NSThreads的显式创建。然而,这两种方法之间的关系对我来说并不清楚,所以任何反馈都很感激!

130995 次浏览

GCD是一个低级的基于c语言的API,可以非常简单地使用基于任务的并发模型。NSOperationNSOperationQueue是Objective-C类,做类似的事情。NSOperation是首先引入的,但从10.5iOS 2开始,NSOperationQueue及其友项在内部使用GCD实现。

一般来说,您应该使用适合您需要的最高级别的抽象。这意味着你通常应该使用NSOperationQueue而不是GCD,除非你需要做一些NSOperationQueue不支持的事情。

注意NSOperationQueue不是GCD的“简化”版本;事实上,你可以用NSOperationQueue非常简单地做很多事情,而这些事情需要用纯GCD做很多工作。(例如:带宽受限的队列一次只能运行N个操作;建立操作之间的依赖关系。NSOperation非常简单,GCD非常困难。)苹果已经做了艰苦的工作,利用GCD用NSOperation创建了一个非常好的对象友好的API。好好利用他们的工作,除非你有理由不这么做。

< p > 警告: 另一方面,如果你真的只需要发送一个块,而不需要NSOperationQueue提供的任何额外功能,那么使用GCD没有任何问题。只要确保它是适合这项工作的工具就可以了

GCD确实比NSOperationQueue级别低,它的主要优势是它的实现非常轻量级,并且专注于无锁算法和性能。

NSOperationQueue确实提供了GCD中无法提供的功能,但它们的成本非常高,NSOperationQueue的实现非常复杂和繁重,涉及大量的锁定,并且在内部只以非常少的方式使用GCD。

如果您需要NSOperationQueue提供的功能,请务必使用它,但如果GCD足以满足您的需求,我建议直接使用它,以获得更好的性能、显著降低CPU和电源成本以及更大的灵活性。

我对一个相关问题的回答一致,我不同意BJ,并建议你首先查看GCD而不是NSOperation / NSOperationQueue,除非后者提供了GCD所不提供的东西。

在GCD之前,我在我的应用程序中使用了很多NSOperations / NSOperationQueues来管理并发。然而,自从我开始在常规的基础上使用GCD,我几乎完全用块和分派队列替换了NSOperations和NSOperationQueues。这来自于我在实践中使用这两种技术的方式,以及我对它们进行的分析。

首先,在使用NSOperations和NSOperationQueues时,有一个不小的开销。这些是Cocoa对象,需要对它们进行分配和释放。在我编写的一个以60 FPS渲染3d场景的iOS应用程序中,我使用NSOperations封装每个渲染帧。当我对此进行分析时,这些NSOperations的创建和删除占据了运行应用程序中CPU周期的很大一部分,并降低了速度。我用简单的块和GCD串行队列替换了这些,开销消失了,呈现性能明显更好。这不是我注意到使用NSOperations开销的唯一地方,我在Mac和iOS上都见过这种情况。

其次,基于块的分派代码有一种优雅,这在使用NSOperations时很难匹配。在一个块中包装几行代码并分派它在串行或并发队列上执行是非常方便的,其中创建一个自定义NSOperation或NSInvocationOperation来做这件事需要更多的支持代码。我知道你可以使用NSBlockOperation,但是你也可以调度一些东西到GCD。在我看来,与使用单独的方法或自定义NSOperations封装这些任务相比,将这些代码封装在应用程序中相关处理的内联块中会导致更好的代码组织。

NSOperations和NSOperationQueues仍然有很好的用途。GCD没有真正的依赖关系概念,NSOperationQueues可以建立相当复杂的依赖关系图。我在少数情况下使用NSOperationQueues。

总的来说,虽然我通常主张使用最高级别的抽象来完成任务,但在这种情况下,我主张使用GCD的低级API。在与我交谈过的iOS和Mac开发者中,绝大多数人选择使用GCD而不是NSOperations,除非他们的目标操作系统版本不支持GCD (iOS 4.0和Snow Leopard之前的版本)。

选择NSOperation而不是GCD的另一个原因是NSOperation的取消机制。例如,一个像500px这样显示数十张照片的App,使用NSOperation我们可以在滚动表格视图或集合视图时取消对不可见图像单元格的请求,这可以极大地提高App性能并减少内存占用。GCD不容易支持这一点。

同样使用NSOperation,可以实现KVO。

在这里是一篇来自Eschaton的文章,值得一读。

GCD非常容易使用——如果你想在后台做一些事情,你所需要做的就是编写代码并在后台队列上分派它。用NSOperation做同样的事情需要大量额外的工作。

NSOperation的优点是(a)你有一个可以发送消息的真实对象,(b)你可以取消一个NSOperation。这不是小事。你需要子类化NSOperation,你必须正确地写你的代码,这样取消和正确地完成任务都能正常工作。简单的你使用GCD,复杂的你创建NSOperation的子类。(有子类NSInvocationOperation和NSBlockOperation,但是它们做的任何事情都更容易在GCD中完成,所以没有好的理由使用它们)。

NSOperations只是一个建立在Grand Central Dispatch之上的API。当你使用NSOperations时,你仍然在使用中央调度。 只是NSOperations给了你一些你可能喜欢的奇特特性。你可以让一些操作依赖于其他操作,在你求和后重新排序队列,以及其他类似的事情。 事实上,ImageGrabber已经在使用NSOperations和操作队列了!ASIHTTPRequest在底层使用它们,如果愿意,可以配置它用于不同行为的操作队列。 那么你应该用哪一种呢?任何对你的应用有意义的都可以。对于这个应用程序,它非常简单,所以我们直接使用中央调度,不需要NSOperation的花哨功能。但如果你的应用需要它们,请随意使用!< / p >

NSQueueOperations和GCD都允许在后台通过释放UI Application Main Tread在不同的线程上执行繁重的计算任务。

好吧,根据之前的文章,我们看到NSOperations有addDependency,这样你就可以把你的操作依次排队。

但是我也读过关于GCD的串行队列,你可以使用dispatch_queue_create在队列中创建运行你的操作。这将允许以顺序的方式一个接一个地运行一组操作。

NSQueueOperation相对于GCD的优势:

  1. 它允许添加依赖和允许您删除依赖,因此对于一个事务,您可以使用依赖顺序运行,而对于其他事务,同时运行GCD 不允许以这种方式运行。

  2. 如果某个操作在队列中,则很容易取消该操作;如果某个操作正在运行,则可以停止该操作。

  3. 可定义最大并发操作数。

  4. 您可以暂停正在队列中的操作

  5. 您可以发现队列中有多少挂起的操作。

GCD是一个低级的基于c语言的API NSOperationNSOperationQueue是Objective-C类 NSOperationQueue是objective C对GCD的包装。 如果使用NSOperation,则隐式使用中央调度中心。

< p > GCD相对于NSOperation的优势: < br > 我实现。 < br > 对于GCD的实现是非常轻量级的
NSOperationQueue是复杂和重量级的

NSOperation相对于GCD的优势:

< p > i.控制运行 < br > 你可以暂停,取消,恢复NSOperation

< p > 2依赖关系 < br > 你可以在两个NSOperations
之间建立依赖关系 直到finished的所有依赖项返回true,操作才会启动 < p > 3运行状态 < br > 可以监视操作或操作队列的状态。

.

. < p > iv.最大操作次数 < br > 可以指定可以同时运行的最大排队操作数

< p > 什么时候使用__ABC0或NSOperation < br > 当你想对队列有更多的控制时(上面提到的),使用NSOperation 对于简单的情况,你想要更少的开销 (你只是想做一些“进入后台”的工作,很少额外的工作)使用GCD

< p > 裁判: < br > https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/ < a href = " https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/ " > < / > http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html < a href = " http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html " > < / > http://nshipster.com/nsoperation/ < / p >

我同意@Sangram和其他回答,但想补充几点。如果我错了,请指正。

我认为现在一天@Sangram的答案的前两点是无效的。我们也可以通过使用GCD来实现这两点。试图通过代码来解释(不要关注代码的质量,这仅供参考)

func methodsOfGCD() {
    

let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
    

    

//We can suspend and resume Like this
concurrentQueue.suspend()
concurrentQueue.resume()
    

//We can cancel using DispatchWorkItem
let workItem = DispatchWorkItem {
print("Do something")
}
concurrentQueue.async(execute: workItem)
workItem.cancel()
    

//Cam add dependency like this.
//Operation 1
concurrentQueue.async(flags: .barrier) {
print("Operation1")
}


//Operation 2
concurrentQueue.async(flags: .barrier) {
print("Operation2")
}


//Operation 3.
//Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
concurrentQueue.async(flags: .barrier) {
print("Operation3")


}


}