ios多线程-NSOperation

ios开发中GCD使用很方便,开发中也应用到,NSOperation是对GCD的封装,主流框架多线程大多是使用NSOperation进行多线程开发
  • NSOperation对比GCD
    • NSOperation基于GCD封装,拥有更多的API
    • 在NSOperationQueue中可以指定NSOperation之间的依赖关系
    • 可以使用KVO监听状态
    • 可定制性,可以继承NSOperation实现可复用的逻辑模块

NSOperation的子类

  • NSInnvocationOperation
  • NSBlockOperation

  1. 使用子类NSInvocationOperation
 NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];

    [operation start];
    - (void)test
{
    NSLog(@"%@",[NSThread currentThread]);
}

输出结果

2017-11-02 13:11:27.259 TestApp[7602:842337] <NSThread: 0x600000075b80>{number = 1, name = main}

结果看,单独使用NSInvocationOperation 是在主线程上执行的

2.子类NSBlockOperation

 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"%@",[NSThread currentThread]);
    }];

    [operation start];

输出结果

2017-11-02 13:15:31.283 TestApp[7700:865333] <NSThread: 0x608000260380>{number = 1, name = main}

NSBlockOperation 单独一个执行的时候也是在主线程

为NSBlockOperation添加额外的操作 addExecutionBlock


    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"%@",[NSThread currentThread]);
    }];


    [operation addExecutionBlock:^{
        NSLog(@"2======%@",[NSThread currentThread]);
    }];

    [operation addExecutionBlock:^{
        NSLog(@"3=======%@",[NSThread currentThread]);
    }];

     [operation start];

输出结果

2017-11-02 13:19:34.229 TestApp[7823:890592] 3=======<NSThread: 0x618000067240>{number = 4, name = (null)}
2017-11-02 13:19:34.228 TestApp[7823:890554] <NSThread: 0x618000065240>{number = 1, name = main}
2017-11-02 13:19:34.229 TestApp[7823:890593] 2======<NSThread: 0x6100000673c0>{number = 3, name = (null)}

可以看到NSBlockOperation在主线程执行,为其添加的操作是在子线程执行的

队列NSOperationQueue

  • 主队列
  • 其他队列 (串行,并发功能)

  • 添加到主队列的任务(nsoperation)都会在主线程执行
    NSOperationQueue *mainqueue = [NSOperationQueue mainQueue];

    [mainqueue addOperationWithBlock:^{
        NSLog(@"1=====%@",[NSThread currentThread]);

    }];


    [mainqueue addOperationWithBlock:^{
        NSLog(@"2=======%@",[NSThread currentThread]);

    }];

输出
2017-11-02 13:27:03.589 TestApp[7979:917764] 1=====<NSThread: 0x6180000755c0>{number = 1, name = main}
2017-11-02 13:27:03.590 TestApp[7979:917764] 2=======<NSThread: 0x6180000755c0>{number = 1, name = main}

验证了,任务添加到主队列添加任务都在主队列

其他队列

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

    NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

        for (int i = 0; i < 3; i++) {
            NSLog(@"1====%@",[NSThread currentThread]);
        }
    }];

    //添加到队列中
    [operationQueue addOperation:op1];
    [operationQueue addOperation:op2];  
}

- (void)test
{
    for (int i = 0; i < 3; i++) {
        NSLog(@"2====%@",[NSThread currentThread]);
    }
}

输出结果

2017-11-02 13:34:26.810 TestApp[8159:944287] 2====<NSThread: 0x610000071740>{number = 3, name = (null)}
2017-11-02 13:34:26.810 TestApp[8159:944307] 1====<NSThread: 0x618000071b80>{number = 4, name = (null)}
2017-11-02 13:34:26.810 TestApp[8159:944287] 2====<NSThread: 0x610000071740>{number = 3, name = (null)}
2017-11-02 13:34:26.810 TestApp[8159:944307] 1====<NSThread: 0x618000071b80>{number = 4, name = (null)}
2017-11-02 13:34:26.812 TestApp[8159:944307] 1====<NSThread: 0x618000071b80>{number = 4, name = (null)}
2017-11-02 13:34:26.812 TestApp[8159:944287] 2====<NSThread: 0x610000071740>{number = 3, name = (null)}

看到 NSInvocationOperation 与NSBlockOperation 和 NSOperationQueue结合能开辟线程,并发执行任务

3.重点是要说控制部分(串行与并行)
NSOperationQueue的串行与并行的控制通过maxConcurrentOperationCount的值大小控制

  • 为-1是默认的值表示不限制为并发执行
  • 为1时为串行执行
  • 大于1时并发执行
```
  NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //设置最大并发操作数
    queue.maxConcurrentOperationCount = 1;

    //添加操作
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"1====%@",[NSThread currentThread]);

        }
    }];

    [queue addOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"2====%@",[NSThread currentThread]);

        }
    }];


    [queue addOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            NSLog(@"3====%@",[NSThread currentThread]);

        }
    }];

为-1时的结果


2017-11-02 14:03:31.215 TestApp[8789:1047083] 2====<NSThread: 0x610000069d00>{number = 4, name = (null)}
2017-11-02 14:03:31.215 TestApp[8789:1047084] 1====<NSThread: 0x608000065f00>{number = 3, name = (null)}
2017-11-02 14:03:31.215 TestApp[8789:1047086] 3====<NSThread: 0x618000067340>{number = 5, name = (null)}
2017-11-02 14:03:31.215 TestApp[8789:1047083] 2====<NSThread: 0x610000069d00>{number = 4, name = (null)}
2017-11-02 14:03:31.215 TestApp[8789:1047084] 1====<NSThread: 0x608000065f00>{number = 3, name = (null)}
2017-11-02 14:03:31.215 TestApp[8789:1047086] 3====<NSThread: 0x618000067340>{number = 5, name = (null)}
2017-11-02 14:03:31.216 TestApp[8789:1047083] 2====<NSThread: 0x610000069d00>{number = 4, name = (null)}
2017-11-02 14:03:31.216 TestApp[8789:1047084] 1====<NSThread: 0x608000065f00>{number = 3, name = (null)}
2017-11-02 14:03:31.216 TestApp[8789:1047086] 3====<NSThread: 0x618000067340>{number = 5, name = (null)}
可以看出线程为并发执行

为1时的结果

2017-11-02 14:04:55.051 TestApp[8828:1052683] 1====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.051 TestApp[8828:1052683] 1====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.051 TestApp[8828:1052683] 1====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.051 TestApp[8828:1052683] 2====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.052 TestApp[8828:1052683] 2====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.053 TestApp[8828:1052683] 2====<NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-11-02 14:04:55.053 TestApp[8828:1052680] 3====<NSThread: 0x61000006f400>{number = 4, name = (null)}
2017-11-02 14:04:55.053 TestApp[8828:1052680] 3====<NSThread: 0x61000006f400>{number = 4, name = (null)}
2017-11-02 14:04:55.054 TestApp[8828:1052680] 3====<NSThread: 0x61000006f400>{number = 4, name = (null)}

从结果可以看出线程为串行执行

大于1时 取值4

2017-11-02 14:06:49.731 TestApp[8884:1060085] 2====<NSThread: 0x618000065f80>{number = 4, name = (null)}
2017-11-02 14:06:49.731 TestApp[8884:1060115] 1====<NSThread: 0x61000006aa80>{number = 3, name = (null)}
2017-11-02 14:06:49.731 TestApp[8884:1060089] 3====<NSThread: 0x6000000695c0>{number = 5, name = (null)}
2017-11-02 14:06:49.731 TestApp[8884:1060085] 2====<NSThread: 0x618000065f80>{number = 4, name = (null)}
2017-11-02 14:06:49.731 TestApp[8884:1060115] 1====<NSThread: 0x61000006aa80>{number = 3, name = (null)}
2017-11-02 14:06:49.731 TestApp[8884:1060089] 3====<NSThread: 0x6000000695c0>{number = 5, name = (null)}
2017-11-02 14:06:49.732 TestApp[8884:1060085] 2====<NSThread: 0x618000065f80>{number = 4, name = (null)}
2017-11-02 14:06:49.732 TestApp[8884:1060115] 1====<NSThread: 0x61000006aa80>{number = 3, name = (null)}
2017-11-02 14:06:49.732 TestApp[8884:1060089] 3====<NSThread: 0x6000000695c0>{number = 5, name = (null)}
从结果可以看出线程为并行执行

为队列添加依赖(addDependency)

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1====%@",[NSThread currentThread]);
    }];


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

    [blockOperation addDependency:op2]; //这里添加依赖,谁在前谁后执行(A依赖B,B先执行 ,B依赖A,A先执行)
    [queue addOperation:blockOperation];
    [queue addOperation:op2];

输出结果

2017-11-02 14:13:15.036 TestApp[9035:1091092] 2====<NSThread: 0x600000261ac0>{number = 3, name = (null)}
2017-11-02 14:13:15.037 TestApp[9035:1091120] 1====<NSThread: 0x608000260cc0>{number = 4, name = (null)}

NSOperationQueue的实例方法

  • cancelAllOperations
  • waitUntilAllOperationsAreFinished

首先说(cancelAllOperations)

  • -(void)cancelAllOperations; NSOperationQueue提供的方法,可以取消队列的所有操作

waitUntilAllOperationsAreFinished

    NSLog(@"执行开始");
     NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1====%@",[NSThread currentThread]);
    }];


    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 5; i++) {
        NSLog(@"2====%@",[NSThread currentThread]);
        }
    }];

    [blockOperation addDependency:op2];
    [queue addOperation:blockOperation];
    [queue addOperation:op2];
    [queue waitUntilAllOperationsAreFinished];

    NSLog(@"执行到这了");

执行结果

2017-11-02 14:23:53.152 TestApp[9349:1143454] 执行开始
2017-11-02 14:23:53.153 TestApp[9349:1143501] 2====<NSThread: 0x608000071f40>{number = 3, name = (null)}
2017-11-02 14:23:53.153 TestApp[9349:1143501] 2====<NSThread: 0x608000071f40>{number = 3, name = (null)}
2017-11-02 14:23:53.153 TestApp[9349:1143501] 2====<NSThread: 0x608000071f40>{number = 3, name = (null)}
2017-11-02 14:23:53.154 TestApp[9349:1143501] 2====<NSThread: 0x608000071f40>{number = 3, name = (null)}
2017-11-02 14:23:53.154 TestApp[9349:1143501] 2====<NSThread: 0x608000071f40>{number = 3, name = (null)}
2017-11-02 14:23:53.154 TestApp[9349:1143514] 1====<NSThread: 0x61800006f740>{number = 4, name = (null)}
2017-11-02 14:23:53.155 TestApp[9349:1143454] 执行到这了

是上面的队列执行完成以后才会执行下面的内容

再来看一下没有添加 [queue waitUntilAllOperationsAreFinished]; 的执行结果

2017-11-02 14:31:32.247 TestApp[9512:1179286] 执行开始
2017-11-02 14:31:32.247 TestApp[9512:1179286] 执行到这了
2017-11-02 14:31:32.248 TestApp[9512:1179339] 2====<NSThread: 0x610000074dc0>{number = 3, name = (null)}
2017-11-02 14:31:32.248 TestApp[9512:1179339] 2====<NSThread: 0x610000074dc0>{number = 3, name = (null)}
2017-11-02 14:31:32.248 TestApp[9512:1179339] 2====<NSThread: 0x610000074dc0>{number = 3, name = (null)}
2017-11-02 14:31:32.249 TestApp[9512:1179339] 2====<NSThread: 0x610000074dc0>{number = 3, name = (null)}
2017-11-02 14:31:32.249 TestApp[9512:1179339] 2====<NSThread: 0x610000074dc0>{number = 3, name = (null)}
2017-11-02 14:31:32.250 TestApp[9512:1179356] 1====<NSThread: 0x60000006ee00>{number = 4, name = (null)}
说明任务是都添加队列后才执行的
发布了54 篇原创文章 · 获赞 13 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章