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.
NSOperation queue:-
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 returnstrue
when the operation is ready to execute now orfalse
if there are still unfinished operations on which it is dependent.
isExecuting
: This tells us whether the operation is executing the assigned task.isExecuting
returnstrue
if the operation is working on its task orfalse
if 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 theisFinished
value changes totrue
.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 isCancelled
Effect of cancel()
- 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 InvocationOperation
and BlockOperation
to execute task.
There are mainly three ways to create operations:-
- BlockOperation
- InvocationOperation
- Custom Operations
BlockOperation :-
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.
InvocationOperation:-
In objective C we can create NSInvocationOperation
while it’s not available in Swift.
Custom Operations:-
Subclassing 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:-
call cancel()
method on custom operation:
Operation Queues:-
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,
OperationQueue
limits 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.
The
maxConcurrentOperationCount
is set to1
to 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 waitUntilFinished
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.
Note:
- 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.