iOS中的多线程(关于NSOperation)

1,129 阅读2分钟

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

什么是NSOperation

  • NSOperationNSOperationQueue 是苹果提供给我们的一套多线程解决方案。实际上 NSOperationNSOperationQueue 是基于 GCD 更高一层的封装,完全面向对象。但是比 GCD 更简单易用、代码可读性也更高

NSOperation 的子类

NSOperation 是个抽象类,并不具备封装操作的能力,必须使用它的子类,子类共有三种

  • NSInvocationOperation
  • NSBlockOperation
  • 自定义子类继承 NSOperation ,实现内部相应的方法

关于 NSInvocationOperation

  • 默认情况下,调用了 start 方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作

  • 只有 NSInvocationOperation 放到一个 NSOperationQueue 中,才会异步执行

    示例:

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
        NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
        NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run2) object:nil];
        NSInvocationOperation *operation3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run3) object:nil];
    
        [operation1 start];
        [operation2 start];
        [operation3 start];
    }
    
    - (void)run1{
        NSLog(@"1-%@",[NSThread currentThread]);
    }
    
    - (void)run2{
        NSLog(@"2-%@",[NSThread currentThread]);
    }
    
    - (void)run3{
        NSLog(@"3-%@",[NSThread currentThread]);
    }
    

    log: Snip20211109_2.png


关于 NSBlockOperation

  • NSInvocationOperation 一样,NSBlockOperation 只是将方法换成了 block

    示例:

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
        NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"1--%@",[NSThread currentThread]);
        }];
        NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"2--%@",[NSThread currentThread]);
        }];
        NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"3--%@",[NSThread currentThread]);
        }];
       
        [operation1 start];
        [operation2 start];
        [operation3 start];
    }
    

    log: Snip20211109_3.png

  • NSBlockOperation 可以通过 addExecutionBlock: 添加额外的操作,只要 NSBlockOperation 封装的操作个数大于1,就会异步执行,额外添加任务不一定就是在子线程执行,也可能在主线程。

    示例:

    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1--%@",[NSThread currentThread]);
    }];
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2--%@",[NSThread currentThread]);
    }];
    
    //额外添加任务
    [operation1 addExecutionBlock:^{
        NSLog(@"3--%@",[NSThread currentThread]);
    }];
    [operation1 addExecutionBlock:^{
        NSLog(@"4--%@",[NSThread currentThread]);
    }];
    
    [operation1 start];
    [operation2 start];
    

    log:(1和2的执行是有序的,但是3、4是并发的,且不可控)

    Snip20211109_7.png


自定义子类继承NSOperation

  • 使用自定义子类继承 NSOperation,调用了 start 方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作

  • 在 .m 中重写 main 方法即可,main 方法中就是要执行的操作

    示例:

    //自定义子类继承NSOperation
    #import "Operation.h"
    @implementation Operation
    - (void)main{
        if (!self.isCancelled) {
            NSLog(@"%@",[NSThread currentThread]);
        }
    }
    @end
    
    //调用
    Operation *operation1 = [[Operation alloc]init];
    [operation1 start];   
    Operation *operation2 = [[Operation alloc]init];
    [operation2 start];
    

    log:

    Snip20211109_8.png