iOS Concurrent Programming:NSOperationQueue

In the last article, we learned GCD, one of the most popular and convinent concurrent framework of iOS, here we will learn NSOperationQueue, which is another concurrent api you could use, also it has some difference with GCD. In the sample project, I also gave examples of working with NSOperationQueue, you can downlaod the project source code for detail.

We already know that , it is not easy to control operations added to a dispatch queue, that is you can not cancel an operation which is already added to a dispatch queue(or there is not an easy way to do this). But NSOperationQueue supports this cancel task, this is the biggest difference between them.

NSOperaton

If we want to execute a method in a dispatch queue, we need to construct a block containing this method. Likewise, every code snippet you want to execute in an NSOperationQueue must be an Operation Object, which is an instance of NSOperation class.

You may think it’s tedious to wrapper your own NSOperation object, when you just want to use an existing method or block in NSOperationQueue, Of course apple have taken this into consideration, and iOS provides two classes NSInvocationOperation and NSBlockOperation.

NSInvocationOperation:
A class you use as-is to create an operation object based on an object and selector from your application. You can use this class in cases where you have an existing method that already performs the needed task. Because it does not require subclassing, you can also use this class to create operation objects in a more dynamic fashion.



NSBlockOperation:
A class you use as-is to execute one or more block objects concurrently. Because it can execute more than one block, a block operation object operates using a group semantic; only when all of the associated blocks have finished executing is the operation itself considered finished.

These two classes are very easy to use, you can refer to the document for detail.

NSOperationQueue

Like Seiral and Concurrent dispatch queues, there are also two kinds of NSOperationQueue, serial and concurrent. If you init an NSOperationQueue, it is concurrent by default. The object concurrentQueue is a concurrent queue.

NSOperationQueue* concurrentQueue = [[NSOperationQueue alloc] init];

If you want to configure a queue to serial, you can use the following property:

NSOperationQueue* seiralQueue = [[NSOperationQueue alloc] init];
serialQueue.maxConcurrentOperationCount = 1; //this will set this queue to Serial

In fact, when an operation is going to be executed, NSOperationQueue will start a thread for this operation, thus NSOperationQueue is indeed a thread pool, and the maxConcurrentOperationCount defines how many threads can be executed concurrently in this pool.

#####Cancel Operations and Operation dependency
I recommend you to use NSOperationQueue instead of using GCD, the main reason for this is the cancel operation, another reason is NSOperationQueue is also build upon GCD, when execute an operation, NSOperationQueue will use GCD to init the thread for the operation.

For cancel operation, there are two apis you can use:

[NSOperationQueue cancelAllOperations];
[NSOperation cancel];

Operation Dependency is also one of the reanson you should choose NSOperationQueue. With NSOperation you can define which operation it depends before it’s executed, that is if you want operation A to starts after operation B is finished, you can set operation B as dependency of Operation A. For more info about this, you can refer to the document.

Hope this will be helpful :)