美文网首页
iOS - 多线程(三) NSOperation讲解

iOS - 多线程(三) NSOperation讲解

作者: 伦伦子_f7b3 | 来源:发表于2017-09-01 17:23 被阅读18次

    NSOperation在ios2出来的,后来又基于GCD进行了重写,但是相对于GCD来说可控性更强,并且可以加入操作依赖。

    NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作。系统已经给我们封装了NSBlockOperation和NSInvocationOperation这两个实体类。使用起来也非常简单,不过我们更多的使用是自己继承并定制自己的操作。

    NSOperation 和 GCD对比:

    (1) GCD ,主要多核处理器优化的并发技术,是C语言的

        将任务(block)添加到队列(串行、并行、主队列、全局队列),并且要指定任务的同步、异步;

        线程间的通讯 dispatch_get_main_queue()

        提供了一些 NSOperation不具备的功能:

              一次执行(单例)

              延迟执行

              调度组(NSOperation 也可以做到,但是有点麻烦)

     (2)NSOperation 在iOS 2.0;苹果推出了GCD之后,对NSOperation 进行了重写

        将操作[异步执行的任务]添加到 【并发队列】,就会立刻异步执行,NSOperation需要配合NSOperationQueue使用

         提供了一个些GCD实现起来比较麻烦功能

                 最大并发线程

                 队列的暂停、继续

                 取消所有线程

                 线程依赖(线程A 的执行必须 依赖线程B)(GCD 同步实现!)



    一. 首先对NSOperationQueue说明

             NSOperationQueue相当于GCD中的队列(dispatch_queue_t)。和GCD中的并发队列、串行队列略有不同的是:NSOperationQueue一共有两种队列:主队列、其他队列。其中其他队列同时包含了串行、并发功能。下边是主队列、其他队列的基本创建方法和特点。

            主队列: 凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行;

                         通过 NSOperationQueue *queue = [NSOperationQueue mainQueue] 获取;

            其他队列(同时包含了:并发功能,非主队列):添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行

                         通过NSOperationQueue *queue = [[NSOperationQueue alloc] init]获取;

    那么对于其他队列如何像GCD一样控制串行执行和并行执行呢?     

    这里有个关键参数maxConcurrentOperationCount,叫做最大并发数

    maxConcurrentOperationCount默认情况下为-1,表示不进行限制,默认为并发执行。

    当maxConcurrentOperationCount为1时,可以当作是串行队列,但是本质上其实还是并发队列,只是被限制了一次只能执行一个任务。

    当maxConcurrentOperationCount大于1时,进行并发执行,当然这个值不应超过系统限制,即使自己设置一个很大的值,系统也会自动调整。




    二. 两个系统提供的子类使用介绍 NSInvocationOperation ,NSBlockOperation


    1.NSInvocationOperation使用(2.0就有了)

    -(void)demo{

          //1.队列

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

            q.maxConcurrentOperationCount = 1;

            for (int i = 0; i < 10 ; i++) {

               //创建操作任务

                NSInvocationOperation *op  = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downImage:) object:@(i)];

                //添加到队列

                [q addOperation:op];

            }

    }


    -(void)downImage:(id)objc{

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

    }

    输出结果:


    分析:由于操作任务加入到其他队列中,该队列默认并发数为1,所以相当于串行队列,所以该队列中的任务会串行执行。但是为何不在同一个线程中执行?(疑问)。这里设置为1,效果只是相当于串行队列一样串行执行,但是NSOperationQueue *q = [[NSOperationQueue  alloc]init]本质上是异步并发队列,所以还是会开启多条线程,只是同一时间只能使用其中一条来执行任务而已。


    2.NSBlockOperation使用(4.0才有)

    -(void)demo{

              //1.队列

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

               //2.操作

              for (int i = 0; i < 10;i++) {

                    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

                         NSLog(@"%@----%d",[NSThread currentThread],i);

                   }];

                   //操作添加到队列

                    [q addOperation:op];

          }

    }

    输出结果:

    分析:由于操作任务加入到其他队列中,该队列默认并发数为默认值,所以为并发队列,所以该队列中的任务会并行执行




    3.不使用NSOperation子类,直接使用NSOperationQueue添加任务


         -(void)demo{

                   //1.队列

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

                 //2.操作任务直接以block的形式添加到队列中

                 for (int i = 0; i < 10;i++) {

                        [q addOperationWithBlock:^{

                                NSLog(@"%@----%d",[NSThread currentThread],i);

                         }];

                   }

            }

    输出结果:

    4.线程间通信

      

          -(void)demo6{

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

                     [q addOperationWithBlock:^{

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

                             //主线程

                              [[NSOperationQueue mainQueue] addOperationWithBlock:^{

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

                              }];

                    }];

           }

    输入结果:


    三.自定义实现一个NSOperation的子类

    相关文章

      网友评论

          本文标题:iOS - 多线程(三) NSOperation讲解

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