“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 property
maxConcurrentOperationCount
Set 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: