“This is the 12th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

About NSOperationQueue

There are two types of NSOperationQueue:

  • The home side column

    // Get the main queue
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    Copy the code
  • Custom queues: Controls whether tasks are executed concurrently or sequentially by setting the maximum concurrency property

    • Concurrent execution
    • The serial execution
    // Get the custom queue
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    Copy the code

NSInvocationOperation and NSOperationQueue

Example:

// Create a queue (tasks in a queue are executed asynchronously by default)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];

// Create a task
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run2) object:nil];

// Add tasks to the queue
[queue addOperation:op1];
[queue addOperation:op2];


- (void)run1{
    NSLog(@"1 - % @",[NSThread currentThread]);
}
- (void)run2{
    NSLog(@"2 - % @",[NSThread currentThread]);
}
Copy the code

The log:


NSInvocationOperation and NSBlockOperation

Example:

// Create a queue (tasks in a queue are executed asynchronously by default)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];

// Create a task
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"1 - % @",[NSThread currentThread]);
}];

NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"2 - % @",[NSThread currentThread]);
}];

// Add extra tasks
[op1 addExecutionBlock:^{
    NSLog(@"3 - % @",[NSThread currentThread]);
}];

// Add extra tasks
[op1 addExecutionBlock:^{
    NSLog(@"4 - % @",[NSThread currentThread]);
}];

// Add tasks to the queue
[queue addOperation:op1];
[queue addOperation:op2];

// You can create tasks directly in the queue
[queue addOperationWithBlock:^{
    NSLog(@5 - "% @",[NSThread currentThread]);
}];
Copy the code

Log :(tasks are executed concurrently)


NSInvocationOperation and custom NSOperation

Example:

// Create a queue (tasks in a queue are executed asynchronously by default)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];

// Create a task that inherits from NSOperation and performs operations that need to be placed in the main of the custom class
Operation *op1 = [[Operation alloc]init];

// Create a task that inherits from NSOperation and performs operations that need to be placed in the main of the custom class
Operation *op2 = [[Operation alloc]init];

// Add tasks to the queue
[queue addOperation:op1];
[queue addOperation:op2];
Copy the code

The log:


NSOperation Other usage

Set the maximum number of concurrent tasks (control concurrent and serial tasks)

  • Maximum concurrency: The maximum number of tasks that a queue can execute at a time
  • Through propertymaxConcurrentOperationCountSet the maximum number of concurrent requests
    • MaxConcurrentOperationCount = 1, without limitation, concurrent execution
    • MaxConcurrentOperationCount = 1, serial queue, serial execution
    • MaxConcurrentOperationCount > 1, concurrent queue, concurrent execution
    • MaxConcurrentOperationCount = 0, do not perform

Note:

  • Maximum number of tasks that can be executed at one time
  • Serial execution is not just opening one thread, it’s just thread synchronization, and the difference between serial and parallel is not how many threads it’s opening, but how the task is being executed, whether it’s ordered or out of order

Example :(set the maximum number of concurrent tasks to 1 and the queue to execute tasks sequentially)

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

// Set the maximum number of concurrent requests to 1
queue.maxConcurrentOperationCount  = 1;

[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"1 - % @",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"2 - % @",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"3 - % @",[NSThread currentThread]);
}];
Copy the code

Log :(multiple threads, but thread synchronization)

Example :(set the maximum number of concurrent tasks to 2 and the queue to execute tasks sequentially)

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

// Set the maximum number of concurrent requests to 1
queue.maxConcurrentOperationCount  = 2;

[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"1 - % @",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"2 - % @",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"3 - % @",[NSThread currentThread]);
}];
Copy the code

Log :(multiple threads, executed asynchronously, no matter how many operations are added to the queue, the actual number of concurrent queue is 2)

Pause and resume queues and cancel them

  • Pause and resume queues

    • Pause indicates that the next task in the queue does not continue. The pause can be recovered
    • Tasks in queues are stateful, including completed, executing, and queuing
    • You cannot suspend a task that is currently in execution
    / / pause
    queue.suspended = YES;
    / / recovery
    queue.suspended = NO;
    Copy the code
  • Unqueue all operations

    • Cancel all operations in the queue
    • After cancellation, the next operation of the current operation will not be performed
    • The cancellation operation is not recoverable
    • The operation has been canceled. You need to join the queue again
    [queue cancelAllOperations]
    Copy the code

Example:

Create the queue and execute

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.queue = [[NSOperationQueue alloc]init];
    self.queue.maxConcurrentOperationCount = 1;
    
    [self.queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"1 - % @",[NSThread currentThread]);
    }];
    
    [self.queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"- 2 - % @",[NSThread currentThread]);
    }];
    
    [self.queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"- 3 - % @",[NSThread currentThread]);
    }];
    
    [self.queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"- 4 - % @",[NSThread currentThread]);
    }];
}

// Pause and resume queues
- (void)suspendedClick:(id)sender {
    if(self.queue.suspended){
        // Restore the queue and continue
        self.queue.suspended  = NO;
    }else{
        // Suspend (pause queue)self.queue.suspended = YES; }}// Unqueue
- (void)cancelClick:(id)sender {
    [self.queue cancelAllOperations];
}
Copy the code

Set the queue operation dependency

  • You can set dependencies between NSOperations to ensure the execution sequence. For example, you can set dependencies after A is executed and then B is executed
  • Set the dependence
    [op1 addDependency:op3];
    Copy the code
  • Cancel the rely on
    [op1 removeDependency:op3];
    Copy the code
  • Circular dependencies cannot be used
    [op1 addDependency:op3];
    [op3 addDependency:op1];
    Copy the code
  • Set listening: Listens for the completion of an operation
    [op2 setCompletionBlock:^{
        NSLog(@"2 Execution completed");
    }];
    Copy the code

Example:

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

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"1 - % @",[NSThread currentThread]);
}];

NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"2 - % @",[NSThread currentThread]);
}];

NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"3 - % @",[NSThread currentThread]);
}];

// Set dependencies (op1 and op3 are done before executing 2)
[op1 addDependency:op3];
[op2 addDependency:op1];

[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];

// Listen for the completion of an operation
[op2 setCompletionBlock:^{
    NSLog(@"2 Execution completed");
}];
Copy the code

Log :(op3 > OP1 > OP2, the monitored operation may not be in the same thread as the monitored operation, both are asynchronous, but op3 will execute the monitored operation after execution.)

Monitors the properties of the NSOperation object

  • IsExecuting: The task is being executed
  • IsFinished Indicates that the task is complete. If the task is canceled, the task is complete
  • IsCancelled indicates that the mission has been cancelled
  • IsAsynchronous indicates whether the task is executed concurrently or synchronously
  • IsReady indicates whether the task is executed concurrently or synchronously

The priority in the queue

  • Before iOS8, NSOperation set priority by setting the queuePriority property
  • After iOS 8.0, NSOperation sets the priority by setting qualityOfService
  • The value with a higher priority is executed first, and the value with a lower priority is executed later
// queuePriority before iOS8
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};

// priority after iOS8 (qualityOfService)
typedef NS_ENUM(NSInteger, NSQualityOfService) {
    NSQualityOfServiceUserInteractive = 0x21.// Highest priority, for user interaction events
    NSQualityOfServiceUserInitiated = 0x19.// Second high priority, for events that the user needs to execute immediately
    NSQualityOfServiceUtility = 0x11.// Default priority. This is the default priority for both main threads and unset threads
    NSQualityOfServiceBackground = 0x09.// Common priority, used for common tasks
    NSQualityOfServiceDefault = -1// Lowest priority, used for unimportant tasks
}
Copy the code
NSOperationQueue *queue = [[NSOperationQueue alloc]init];

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"down1---%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"down2---%@",[NSThread currentThread]);
    
}];

NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"down3---%@",[NSThread currentThread]);
    
}];

// Set the priority
op3.qualityOfService = NSQualityOfServiceUserInteractive;

[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
Copy the code

The log: