美文网首页
NSOperation

NSOperation

作者: 傲骨天成科技 | 来源:发表于2020-03-26 19:24 被阅读0次

NSOperation分为三种:NSInvocationOperation、NSBlockOperation、NSOperation自定义

一、NSInvocationOperation讲解

1.不能开辟子线程的NSInvocationOperation

NSInvocationOperation *operation = [[NSInvocationOperation  alloc]  initWithTarget:self selector:@selector(invocationTest0) object:nil];

// 执行此操作
[operation start];

- (void ) invocationTest0 {
    
    NSLog(@"invocationTest0===%@",[NSThread currentThread]);
}

结果为:invocationTest0===<NSThread: 0x28386a380>{number = 1, name = main}

由于没有把创建的操作添加到队列中,所以不具备开辟子线程的能力。

2.能开辟子线程的NSInvocationOperation

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest0) object:nil];

// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];

- (void ) invocationTest0 {
    
    NSLog(@"invocationTest0===%@",[NSThread currentThread]);
}
结果为:invocationTest0===<NSThread: 0x281094340>{number = 4, name = (null)}

由于创建了队列并把创建的操作添加到了队列中,所以具备了开辟新线程的能力
同时不需要操作执行start方法就可以自动执行。

二、NSBlockOperation讲解

1.不能开辟新线程的NSBlockOperation

// 创建方式一
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
       
        NSLog(@"userBlockOperation0==%@",[NSThread currentThread]);
    }];
    [operation start];
    
    // 创建方式二
    NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
    [operation1 addExecutionBlock:^{
       
        NSLog(@"userBlockOperation0addExecutionBlock==%@",[NSThread currentThread]);
    }];
    [operation1 start];

结果为:userBlockOperation0==<NSThread: 0x280c86380>{number = 1, name = main}
userBlockOperation0addExecutionBlock==<NSThread: 0x280c86380>{number = 1, name = main}

从结果可以看出,当NSBlockOperation不添加到队列中,直接进行start的时候,是不具有开辟新线程的能力的。

2.能开辟新线程的NSBlockOperation

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"最大并发数可以控制我==%@",[NSThread currentThread]);
    }];
    
    
    [operation1 addExecutionBlock:^{
        
        // 设置最大并发数不可以控制我的,我是异步的,会开辟子线程,不需要添加到队列中
        NSLog(@"block0==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block1==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block2==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block3==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block4==%@",[NSThread currentThread]);
    }];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation1];

结果:
最大并发数可以控制我==<NSThread: 0x282d8de40>{number = 4, name = (null)}
block0==<NSThread: 0x282dbcf80>{number = 5, name = (null)}
block1==<NSThread: 0x282d8de40>{number = 4, name = (null)}
block2==<NSThread: 0x282dbcf80>{number = 5, name = (null)}
block3==<NSThread: 0x282d81a80>{number = 6, name = (null)}
block4==<NSThread: 0x282d8de40>{number = 4, name = (null)}

从结果可以看出,当NSBlockOperation添加到队列中,具有开辟新线程的能力的。

三、添加依赖

1.NSInvocationOperation添加依赖

/// 加入到队列中,会创建子线程
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest0) object:nil];
    
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest1) object:nil];

    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest2) object:nil];
    
    // 添加依赖,前面的依赖后面的,就是先执行后面的
    [operation1 addDependency:operation];
    [operation addDependency:operation2];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation];
    [queue addOperation:operation1];
    [queue addOperation:operation2];

结果是:
invocationTest2===<NSThread: 0x281c5e540>{number = 6, name = (null)}
invocationTest0===<NSThread: 0x281c5e540>{number = 6, name = (null)}
invocationTest1===<NSThread: 0x281c5e540>{number = 6, name = (null)}

从结果可以看出,当Operation有依赖关系的时候,会先执行后面的操作。

2.NSBlockOperation添加依赖

// 创建要执行的任务
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        
        NSLog(@"operation1==%@",[NSThread currentThread]);

    }];
    
    // 给对应的操作再添加任务
    [operation1 addExecutionBlock:^{
        
        NSLog(@"operation1_addExecutionBlock0==%@",[NSThread currentThread]);
    }];
    
    [operation1 addExecutionBlock:^{
        
        NSLog(@"operation1_addExecutionBlock1==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        
        NSLog(@"operation2==%@",[NSThread currentThread]);
    }];
    
    [operation2 addExecutionBlock:^{
        
        NSLog(@"operation2_addExecutionBlock0==%@",[NSThread currentThread]);
    }];
    
    [operation2 addExecutionBlock:^{
        
        NSLog(@"operation2_addExecutionBlock1==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        
        NSLog(@"operation3==%@",[NSThread currentThread]);
        
       
    }];
    
    // 设置依赖,任务1依赖于任务二,任务二依赖于任务三,执行顺序是3、2、1
    [operation1 addDependency:operation2];
    [operation2 addDependency:operation3];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];

结果是:
operation3==<NSThread: 0x282140500>{number = 4, name = (null)}
operation2==<NSThread: 0x282140500>{number = 4, name = (null)}
operation2_addExecutionBlock0==<NSThread: 0x282143640>{number = 5, name = (null)}
operation2_addExecutionBlock1==<NSThread: 0x28214c100>{number = 3, name = (null)}
operation1_addExecutionBlock1==<NSThread: 0x282143640>{number = 5, name = (null)}
operation1_addExecutionBlock0==<NSThread: 0x28214c100>{number = 3, name = (null)}
operation1==<NSThread: 0x282140500>{number = 4, name = (null)}

从结果来看NSBlockOperation添加依赖和NSInvocationOperation依赖一样,都是先执行后面的操作。但是如果某个操作右添加了相关的任务就,那么执行所有操作的顺序不变,每个操作中再添加的所有任务就是异步的。

四、设置最大操作并发数

1.NSInvocationOperation设置最大并发数

/// 加入到队列中,会创建子线程
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest0) object:nil];
    
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest1) object:nil];

    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest2) object:nil];
    
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    [queue addOperation:operation];
    [queue addOperation:operation1];
    [queue addOperation:operation2];

- (void ) invocationTest0 {
    
    NSLog(@"invocationTest0===%@",[NSThread currentThread]);
}

结果是:
invocationTest0===<NSThread: 0x280f847c0>{number = 4, name = (null)}
invocationTest1===<NSThread: 0x280f847c0>{number = 4, name = (null)}
invocationTest2===<NSThread: 0x280f9ce00>{number = 6, name = (null)}

从结果看,当设置最大并发操作数量为1的时候,执行操作的顺序就是对应的操作添加到队列的顺序,这时就相当于添加了依赖。
当最大并发操作数量为大于1的时候,执行顺序就是会乱,同一时间会执行多个操作。

2.NSBlockOperation设置最大并发数

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        
       
        NSLog(@"operation1==%@",[NSThread currentThread]);
    }];
    
    
    [operation1 addExecutionBlock:^{
        
        
        NSLog(@"block0==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block1==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block2==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block3==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block4==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation2==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation3==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation4==%@",[NSThread currentThread]);
    }];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    [queue addOperation:operation4];


结果是:
operation1==<NSThread: 0x2800e4b80>{number = 6, name = (null)}
block1==<NSThread: 0x2800e4740>{number = 7, name = (null)}
block2==<NSThread: 0x2800e4740>{number = 7, name = (null)}
block4==<NSThread: 0x2800de280>{number = 8, name = (null)}
block3==<NSThread: 0x2800e4740>{number = 7, name = (null)}
block0==<NSThread: 0x2800e4b80>{number = 6, name = (null)}
operation2==<NSThread: 0x2800e4b80>{number = 6, name = (null)}
operation3==<NSThread: 0x2800e4b80>{number = 6, name = (null)}
operation4==<NSThread: 0x2800e4b80>{number = 6, name = (null)}

从结果可以看出,当设置最大并发操作数量为1的时候,执行操作的顺序就是对应的操作添加到队列的顺序,但是每个操作中添加的任务就是异步的了(没有顺序)。

五、设置优先级

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        
       
        NSLog(@"operation1==%@",[NSThread currentThread]);
    }];
    
    
    [operation1 addExecutionBlock:^{
        
        
        NSLog(@"block0==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block1==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block2==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block3==%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        
        NSLog(@"block4==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        
        sleep(2);
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation2==%@",[NSThread currentThread]);
    }];
    operation2.queuePriority = NSOperationQueuePriorityVeryHigh;
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation3==%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 我在当前的队列线程中,比如不添加相关队列,直接执行就是在主线程中的
        NSLog(@"operation4==%@",[NSThread currentThread]);
    }];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    [queue addOperation:operation4];

结果是:
operation1==<NSThread: 0x2817edd40>{number = 3, name = (null)}
block0==<NSThread: 0x2817edd40>{number = 3, name = (null)}
operation3==<NSThread: 0x281799040>{number = 6, name = (null)}
block1==<NSThread: 0x2817edd40>{number = 3, name = (null)}
block2==<NSThread: 0x281799040>{number = 6, name = (null)}
block3==<NSThread: 0x2817edd40>{number = 3, name = (null)}
block4==<NSThread: 0x281799040>{number = 6, name = (null)}
operation4==<NSThread: 0x2817b2840>{number = 4, name = (null)}
operation2==<NSThread: 0x2817b5300>{number = 5, name = (null)}

从结果看出,给操作设置优先级只是说此操作执行的顺友优先级排在前面,但是具体执行完毕后是否在最前面还是决定于操作内任务的多少。

六、队列的挂起和取消

操作已经被调度的时候是不能挂起和取消的。
取消操作其实就是移除了此操作

相关文章

网友评论

      本文标题:NSOperation

      本文链接:https://www.haomeiwen.com/subject/oqpxuhtx.html