美文网首页
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