Introduction to NSOpreation and NSOperationQueue

  • NSOperation and NSOperationQueue are multi-threaded solutions provided by Apple.
  • NSOperation and NSOperationQueue are based on the higher level of GCD encapsulation and are fully object-oriented.
  • Although it is packaged based on GCD, it is easier to use and more readable than GCD.
  • Some of the concepts in GCD also apply to NSOperation and NSOperationQueue. There are similar concepts of tasks (operations) and queues (operation queues) in NSOperation and NSOperationQueue.
  • In NSOperation, as NSOperation is an abstract class, we need to use the subclasses of NSOperation, NSInvocationOperation and NSBlockOperation.

What is abstract class? An abstract class is incomplete and can only be used as a base class. In the object-oriented approach, abstract classes are primarily used for type hiding and acting as global variables. From Baidu Encyclopedia

NSOpreation and NSOperationQueue

Create a queue NSOperationQueue
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
Copy the code
Create operation NSOpreation
  • NSInvocationOperation
    NSInvocationOperation *io = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(InvocationOperationSelector) object:nil];

    [io start];    

    -(void)InvocationOperationSelector{
        NSLog(@"This is the task performed by NSInvocationOperation %@",[NSThread currentThread]);
    }
Copy the code

The output

The task is executed on the main thread, and the thread is not started.

  • NSBlockOperation
    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"This is the task performed by NSBlockOperation %@",[NSThread currentThread]);
    }];
    
    [bo start];
Copy the code

The output

NSInvocationOperation

  • NSBlockOperation adds additional tasks
    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"This is the task performed by NSBlockOperation %@",[NSThread currentThread]);
    }];
    
    [bo addExecutionBlock:^{
        NSLog(@"This is another task for NSBlockOperation %@",[NSThread currentThread]);
    }];
    
    [bo addExecutionBlock:^{
        NSLog(@"This is another task for NSBlockOperation to do 2% @",[NSThread currentThread]);
    }];
    
    [bo start];
Copy the code

The output

NSBlockOperation
blockOperationWithBlock

    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"This is the task performed by NSBlockOperation %@",[NSThread currentThread]); }}]; [bo addExecutionBlock:^{for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"This is another task for NSBlockOperation %@",[NSThread currentThread]); }}]; [bo addExecutionBlock:^{for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"This is another task for NSBlockOperation to do 2% @",[NSThread currentThread]); }}]; [bo start];Copy the code

Print the result

blockOperationWithBlock

1. Whether NSBlockOperation creates a thread depends on the number of tasks that need to be executed. 2. The inside of the blockOperationWithBlock tasks, and no is not necessarily the main thread.

Add operations (NSOpreation) to queues (NSOperationQueue)
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    NSInvocationOperation *io = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(InvocationOperationSelector) object:nil];
   
     NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"This is the task performed by NSBlockOperation %@",[NSThread currentThread]); }}]; [queue addOperation:io]; [queue addOperation:bo];Copy the code

The output

As you can see, both operations create threads with numbers 3 and 4, respectively, which are no longer the main thread.

Note: Start cannot be used with addOperation, otherwise it will crash

Add and remove dependencies

– (void)addDependency:(NSOperation *)op; Add a dependency that makes the current operation dependent on the completion of the operation op. – (void)removeDependency:(NSOperation *)op; Remove a dependency to remove the dependency of the current operation on op.

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

    NSBlockOperation *bo1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"This is the task performed by BO1 %@",[NSThread currentThread]);
    }];
    NSBlockOperation *bo2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"This is what BO2 does %@",[NSThread currentThread]);
    }];
    NSBlockOperation *bo3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"This is what BO3 does %@",[NSThread currentThread]); }]; //bo1 depends on BO2 [bo1 addDependency:bo2]; //bo2 dependency on BO3 [bo2 addDependency:bo3]; [queue addOperations:@[bo1,bo2,bo3]waitUntilFinished:YES];
    
    NSLog(@"If waitUntilFinished above is YES, I will execute last.");
Copy the code

The output

waitUntilFinished

#####NSOperationQueue Controls the maximum number of concurrent requests (for synchronization)

    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    queue.maxConcurrentOperationCount = 1;
    
    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i<5; i++) {
            NSLog(@"Mission %d %@",i+1,[NSThread currentThread]); }}]; [bo addExecutionBlock:^{for (int i = 0; i<5; i++) {
            NSLog(@"Perform additional task %@ for %d",i+1,[NSThread currentThread]); }}]; [queue addOperation:bo];Copy the code

Let’s look at the output



task
Additional tasks



task
Additional tasks


MaxConcurrentOperationCount control is not the number of concurrent threads here, but in a queue at the same time to the maximum number of concurrent execution task. And a task doesn’t have to run in just one thread.

Interthread communication
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 100, 200, 10)];
    [self.view addSubview:label];
    
    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        NSString * str = @"String assignment";
        NSLog(@"This is the child thread %@",[NSThread currentThread]);
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            NSLog(@"Go back to main thread and refresh UI%@",[NSThread currentThread]);
            label.text = str;
        }];
    }];
    [queue addOperation:bo];
Copy the code

Print and display results

Common attributes and methods of NSOperation and NSOperationQueue

NSOperation Common attributes and methods

1. Cancel the operation – (void)cancel; Operations can be cancelled, essentially marking isCancelled status.

2. Check the operation status – (BOOL)isFinished; Check whether the operation is complete. – (BOOL)isCancelled; Determines whether the operation has been marked as cancelled. – (BOOL)isExecuting; Determine whether the operation is running. – (BOOL)isReady; Determines whether an operation is in a ready state. This value depends on the dependency of the operation.

3. Operation synchronization – (void)waitUntilFinished; Blocks the current thread until the operation is complete. Can be used for sequential synchronization of threads. – (void)setCompletionBlock:(void (^)(void))block; CompletionBlock executes the completionBlock when the current operation completes. – (void)addDependency:(NSOperation *)op; Add a dependency that makes the current operation dependent on the completion of the operation op. – (void)removeDependency:(NSOperation *)op; Remove a dependency to remove the dependency of the current operation on op. @property (readonly, copy) NSArray

*dependencies; Array of all action objects that are executed before the current operation begins.

Common properties and methods of NSOperationQueue

1. CancelAllOperations – (void)cancelAllOperations; You can cancel all operations on the queue. – (BOOL)isSuspended; Determines whether the queue is paused. YES indicates the pause state, and NO indicates the recovery state. – (void)setSuspended:(BOOL)b; You can set the pause and resume of an operation. YES stands for pause queue, and NO stands for resume queue.

2. Synchronous operations – (void) waitUntilAllOperationsAreFinished; Blocks the current thread until all operations in the queue have completed.

3. Add/get operation – (void)addOperationWithBlock:(void (^)(void))block; Add an operation object of type NSBlockOperation to the queue. – (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; To add an array of operations to the queue, wait whether to block the current thread until all operations are completed – (NSArray *)operations; An array of operations currently in the queue that are automatically cleared when an operation completes. – (NSUInteger)operationCount; Operands in the current queue.

Queue + (id)currentQueue; Gets the current queue, and returns nil if the current thread is not running on NSOperationQueue. + (id)mainQueue; Gets the main queue.

Part from Xidan _ Night Weiyang