美文网首页
NSOperationQueue

NSOperationQueue

作者: CoderJackieYip | 来源:发表于2016-03-15 04:03 被阅读419次

    NSOperation

    • 一个NSOperation就是一个操作,可以拥有至少一个任务,它可以调用start方法执行任务,默认是同步执行,即在主线程执行
    • 作用:配合使用NSOperation和NSOperationQueue,可以实现多线程编程(即可异步执行任务)
    • NSOperation子类

      • NSOperation是一个抽象类,不具备封装任务(操作)的能力,必须使用它的子类进行封装
      • 使用NSOperation子类的方式有3种:
      • NSInvocationOperation (少用)
      // 如果不添加到队列中,则在主线程上运行操作
       NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nilo];
       [op start];
      
      • NSBlockOperation,如果不添加到队列中,第一个block在主线程运行,添加的额外block在子线程上执行
      NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"任务1--%@", [NSTread currentTread]) // 主线程
      }];
      [op addExecutionBlock:^{
        NSLog(@"任务2--%@", [NSTread currentTread]) // 子线程
      }];
      [op addExecutionBlock:^{
        NSLog(@"任务3--%@", [NSTread currentTread]) // 子线程
      }];
      [op addExecutionBlock:^{
        NSLog(@"任务4--%@", [NSTread currentTread]) // 子线程
      }];
      
      • 自定义子类继承NSOperation,实现内部相应的方法
        // main方法是入口,必须将任务放到main方法中才会执行
        - (void)main {...};
      

    NSOperationQueue

    NSOperationQueue是基于GCD的面向对象的队列

    • NSOperationQueue队列类型
      1. 主队列:任务在主线程执行
      [NSOperationQueue mainQueue];
      
      1. 其他队列(串行、并发):任务在子线程执行
      // 默认并发
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      // 实现串行,可设置 maxConcurrentOperationCount 属性 = 1,其默认值是 -1
      queue.maxConcurrentOperationCount = 1;
      
    • GCD的队列类型
      1. 并发队列:
      • 自己创建的
      • 全局的
      1. 串行队列:
      • 主队列
      • 自己创建的
    • 实现多线程的步骤

      • 方式一:

        1. 创建队列:NSOperationQueue
        2. 创建操作:NSOperation
        3. 将NSOperation对象添加到NSOperationQueue中(系统会自动将NSOperationQueue中的NSOperation取出来,并自动放到一条线程中执行任务)
        • 主线程里执行:放到主队列
        • 子线程里执行:放到其他队列(即创建的队列)
      • 方式二:

        1. 创建队列:NSOperationQueue
        2. 直接将任务添加到队列中。

      具体实现

      /** 方式一 **/
      // 1. 创建队列
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      // 2. 创建操作(任务)
          // 操作1任务1 NSInvocationOperation
      NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil]; 
          // 操作2任务2 NSBlockOperation
      NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{...}];
          // 操作2任务3 NSBlockOperation
      [op2 addExecutionBlock:^{...}];
          // 操作3任务4 使用自定义JKYOperation,该类中需要实现-(void)main方法,并将任务添加其中,才会执行的任务
      JKYOperation *op3 = [[JKYOperation alloc] init];
      // 3. 添加任务到队列中
      [queue addOperation:op1];
      [queue addOperation:op2];
      [queue addOperation:op3];
      
      /** 方式二 **/
      // 1. 创建队列
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      // 2. 添加任务
      [queue addOperationWithBlock:^{...}];
      
      
    • 队列的挂起与取消

    队列执行挂起或取消的同时,operation的任务还在执行,则会执行完当前任务,再停止。

    • 苹果推荐的解决方案:

    自定义NSOperation,并在类中相对耗时的任务后判读当前队列是否处于暂停或取消状态,如果是则return;

    -(void)main {
    //耗时任务执行后,判断
    if(self.isCanceled || self.isSusended) return;
    }
    
    • 操作依赖和监听

    在多线程中,并发执行多个操作,无法控制其调用顺序,可添加依赖实现顺序调用

    具体实现

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{...}];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{...}];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{...}];
    /** 监听 **/
    op3.completionBlock = ^{NSLog(@"op3执行完毕");};
    /** 依赖 **/
    // op3依赖op1,op3依赖op2
    // 可跨队列添加依赖
    [op3 addDependency:op1];
    [op3 addDependency:op2];
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    //
    // 注意:
    // 1. 应在加入队列之前添加依赖
    // 2. 不可两个操作相互添加依赖
    
    • 线程之间通信

    具体实现

    [[NSOperationQueue alloc] init] addOperationWithBlock:^{
      // 图片的网络路径
      NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/123234.jpg"];
      // 加载图片
      NSData *data = [NSDdata dataWithContentsOfURL:url];
      // 生成图片
      UIImage *image = [UIImage imageWithData:data];
      // 回到主线程
      [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        self.imageView.image = image;
      }]
    

    相关文章

      网友评论

          本文标题:NSOperationQueue

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