我正在学习iOS的并发编程。到目前为止,我已经了解了NSOperation/NSOperationQueue和GCD。为什么在GCD上使用NSOperationQueue,反之亦然?
听起来好像GCD和NSOperationQueue都从用户那里抽象出了nsthread的显式创建。然而,这两种方法之间的关系对我来说并不清楚,所以任何反馈都很感激!
我正在学习iOS的并发编程。到目前为止,我已经了解了NSOperation/NSOperationQueue和GCD。为什么在GCD上使用NSOperationQueue,反之亦然?
听起来好像GCD和NSOperationQueue都从用户那里抽象出了nsthread的显式创建。然而,这两种方法之间的关系对我来说并不清楚,所以任何反馈都很感激!
当前回答
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch. It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that. In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like. So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
其他回答
GCD是一个低级的基于c语言的API,可以非常简单地使用基于任务的并发模型。NSOperation和NSOperationQueue是Objective-C类,做类似的事情。NSOperation是最先被引入的,但是从10.5和iOS 2开始,NSOperationQueue和它的朋友是通过GCD内部实现的。
一般来说,您应该使用适合您需要的最高级别的抽象。这意味着你通常应该使用NSOperationQueue而不是GCD,除非你需要做一些NSOperationQueue不支持的事情。
Note that NSOperationQueue isn't a "dumbed-down" version of GCD; in fact, there are many things that you can do very simply with NSOperationQueue that take a lot of work with pure GCD. (Examples: bandwidth-constrained queues that only run N operations at a time; establishing dependencies between operations. Both very simple with NSOperation, very difficult with GCD.) Apple's done the hard work of leveraging GCD to create a very nice object-friendly API with NSOperation. Take advantage of their work unless you have a reason not to.
警告: 另一方面,如果你真的只需要发送一个块,而不需要NSOperationQueue提供的任何附加功能,那么使用GCD也没有什么问题。只要确保它是适合这项工作的工具。
Well, NSOperations are simply an API built on top of Grand Central Dispatch. So when you’re using NSOperations, you’re really still using Grand Central Dispatch. It’s just that NSOperations give you some fancy features that you might like. You can make some operations dependent on other operations, reorder queues after you sumbit items, and other things like that. In fact, ImageGrabber is already using NSOperations and operation queues! ASIHTTPRequest uses them under the hood, and you can configure the operation queue it uses for different behavior if you’d like. So which should you use? Whichever makes sense for your app. For this app it’s pretty simple so we just used Grand Central Dispatch directly, no need for the fancy features of NSOperation. But if you need them for your app, feel free to use it!
GCD非常容易使用——如果你想在后台做一些事情,你所需要做的就是编写代码并在后台队列上分派它。用NSOperation做同样的事情需要大量额外的工作。
The advantage of NSOperation is that (a) you have a real object that you can send messages to, and (b) that you can cancel an NSOperation. That's not trivial. You need to subclass NSOperation, you have to write your code correctly so that cancellation and correctly finishing a task both work correctly. So for simple things you use GCD, and for more complicated things you create a subclass of NSOperation. (There are subclasses NSInvocationOperation and NSBlockOperation, but everything they do is easier done with GCD, so there is no good reason to use them).
GCD确实比NSOperationQueue级别低,它的主要优势是它的实现非常轻量级,并且专注于无锁算法和性能。
NSOperationQueue确实提供了GCD中无法提供的功能,但它们的成本非常高,NSOperationQueue的实现非常复杂和繁重,涉及大量的锁定,并且在内部只以非常少的方式使用GCD。
如果您需要NSOperationQueue提供的功能,请务必使用它,但如果GCD足以满足您的需求,我建议直接使用它,以获得更好的性能、显著降低CPU和电源成本以及更大的灵活性。
我同意@Sangram和其他回答,但想补充几点。如果我错了,请指正。
我认为现在@Sangram的答案的前两点是无效的(I .控制操作ii.)。依赖关系)。我们也可以通过使用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")
}
}