Multithreading in iOS-Part 3/4
NSOperation, advantage of NSOperation, operation
If want to know about what is thread, multi thread and how gcd works please refer my first blog here.
Another way to create thread is using operation. After you have created instances of your operations, submit the operations to OperationQueue. The OperationQueue will manage the threads and also responsible for running the operations that you have provided to it.
What is operation? An abstract class that represents the code and data associated with a single task.
Operation States:- Operation object maintain states internally to determine when it is safe to execute and also to notify external clients of the progress through the operation’s life cycle.
Bellow are the operation states
isReady: It informs client when an operation is ready to execute. This returns
truewhen the operation is ready to execute now or
falseif there are still unfinished operations on which it is dependent.
isExecuting: This tells us whether the operation is executing the assigned task.
trueif the operation is working on its task or
falseif it is not.
isFinished: It informs that an operation finished its task successfully or was cancelled. Operation queue does not dequeue an operation or operation object will not clear until the
isFinishedvalue changes to
isCancelled: This inform clients that the cancellation of an operation was requested.
How can you cancel operation?
We can cancel operation using
cancel() as follows. We can check whether the operation is cancelled or not by
- Your operation is already finished. In that case, the cancel method has no effect.
- Your operation is already being executing. In that case, system will NOT force your operation code to stop but instead, cancelled property will be set to true.
- Your operation is still in the queue waiting to be executed. In that case, your operation will not be executed.
How can we create operation?
Developer no need to use this directly. Foundation provides two system-defined sub classes
BlockOperation to execute task.
There are mainly three ways to create operations:-
- Custom Operations
An operation that manages the concurrent execution of one or more blocks.
BlockOperation class extends from
Operation class. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.
Making use of the system-defined
BlockOperation looks as follows:
Here block operations added into operation queue. Operation queue started that operation on some background thread and execute it.
And can also be done by adding the block directly on the queue:
How can we execute one or more block concurrently?
we can use
BlockOperation to execute one or more block at once without creating new operation as follows
as you can see the tasks/blocks added to the Block operation itself executed concurrently but the block run
synchronous manner means it blocked the thread at which start is called in our case it is main thread.
We can unblock main thread by calling
start() method in any other thread but this will block that thread where
start() method is called.
In objective C we can create
NSInvocationOperation while it’s not available in Swift.
Operation gives you complete control over the implementation of your own operations which includes the ability to alter the default way in which your operation executes and reports its status.
creating custom concurrent operation as follows:-
cancel() method on custom operation:
Operations Queues are Cocoa’s high-level abstraction on GCD. Instead of starting operation by yourself, you give to operation queue. It then handle the scheduling and execution.
An operation queue executes its queued
Operation objects based on their priority and in FIFO order.
An operation queue executes its operations either directly, by running them on secondary threads, or indirectly using the
libdispatch library (i.e. Grand Central Dispatch)
You can add as many operations as you want, but they don’t all get executed at the same time. Instead,
OperationQueuelimits the number of operations based on system conditions
we can cancel operation queue as
Operation queues retain operations until they’re finished. Suspending an operation queue with operations that aren’t finished can result in a memory leak.
How can we set maximum Concurrent Operation on operation queue?
maxConcurrentOperationCount help us to set max concurrent operation but it’s recommended not to set.
maxConcurrentOperationCountis set to
1to allow operations finishing one by one. it act as serial queue
by default value is -1 which means let the system decide
How does the queue decide how many operations it can run at once?
It depends on the hardware. By default,
OperationQueue does some calculation behind the scenes and decides the maximum possible number of threads depending on platform it’s running on.
In which order operation queue executes task?
Operations within a queue are organised according to their readiness i.e. (
isReady property returns
true), priority level & dependencies, and are executed accordingly.
If all of the queued operations have the same
queuePriority and are ready to execute when they are put in the queue, they’re executed in the order in which they were submitted to the queue. Otherwise, the operation queue always executes the one with the highest priority relative to the other ready operations.
An operation object will not be ready to execute until all of its dependent operations have finished executing.
How to add dependency between operation?
Consider a situation where you need to call two api after these api completion you need to parse a response then you need to use dependency manager to achieve this
without dependency between operation
with dependency between operation
Dispatch Group Implementation Using Operations Queue:-
we used GCD dispatch group feature to block a thread until one or more tasks finished executing.
we implemented the same behaviour using Operation Queues by using dependencies. This is useful when you can’t do anything until all of the specified tasks are completed.
In some situation you need to run concurrently and when all the tasks finished we need to call some method to indicate that all tasks has finished. this can be achieve by using
Asynchronous Versus Synchronous Operations:-
If you plan on executing an operation object manually, instead of adding it to a queue, you can design your operation to execute in a synchronous or asynchronous manner.
Operation objects are synchronous by default. When you call the
start() method of a synchronous operation directly from your code, the operation executes immediately in the current thread.
When you call the
start() method of an asynchronous operation, that method may return before the corresponding task is completed. An asynchronous operation object is responsible for scheduling its task on a separate thread.
Benefits of Operation Queues Over GCD:-
- Operation queues are high-level abstraction of the queue model and is made on top of GCD.
- The Operation API provides support for dependencies. You can create complex dependencies between tasks very easily though in GCD you can achieve it but you have to do a lot of work.
- The NSOperation and NSOperationQueue classes have a number of properties that can be observed, using KVO (Key Value Observing).
- You can monitor the state of an operation or operation queue.
- Operations can be paused, resumed, and cancelled. Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. It gives control over operation life cycle
- you can specify the maximum number of queued operations that can run simultaneously. This makes it easy to control how many operations run at the same time or to create a serial operation queue.
7. Unlike GCD, they don’t conform to the First-In-First-Out order.
- For more information on GCD and thread read part-1 blog here:
- For more information on DispatchWorkItem, DispatchGroup, DispatchBarrier, DispatchSemaphore, DispatchSources read part-2 blog here:
- Refer the blog for interview questions and to know about multithread problem
Enjoy your coding. I hope you learnt something from this blog. Please hit the clap button below 👏 to help others find it!. follow me on Medium.