美文网首页
NSOperation

NSOperation

作者: 彼岸的黑色曼陀罗 | 来源:发表于2016-09-26 16:52 被阅读0次

NSOperation

简介

  • 操作就是一个任务

  • 作用

    • 配合NSOperation和NSOperationQueue实现多线程编程
  • 实现多线程的具体步骤

    • 先将需要执行的操作封装到一个NSOperation对象中
    • 然后将NSOperation对象添加到NSOperationQueue中
    • 系统会自动将NSOperationQueue中的NSOperation取出来
    • 将取出的NSOperation封装的操作放到一条新的线程中执行
  • NSOperation的子类

    • NSOperation抽象类,并不具备封装操作的能力,必须使用它的子类
    • 使用NSOperation子类的方式
      • NSInvocationOperation
      • NSBlockOperation
      • 自定义子类继承NSOperation,实现内部相应的方法
    • NSInvocationOperation
      • 了解,本身不好用,开发中不经常用,swift里面没有InvocationOperation的API了

封装操作的几种方式

  • 操作:一个op对象

  • 任务:方法里面的代码

  • NSInvocationOperation

    • 创建一个操作对象NSInvocationOperation alloc]initWithTarget:selector:object:
      • 第一个参数:目标对象self
      • 第二个参数:要调用的方法
      • 第三个参数:要调用方法需要接收的参数
    • 执行操作
      • start开始执行操作
    • 没有开子线程,在当前线程中串行执行
    • 必须要和队列结合起来使用,才能开线程
  • NSBlockOperation

    • 创建操作对象NSBlockOperation blockOperationWithBlock:^{}
    • 执行操作
      • start
    • 没有开子线程,在当前线程中串行执行
    • 特殊:对象方法addExcutionBlock追加任务,可能开子线程的
      • 注意点:NSBlockOperation在使用的时候,如果一个操作中任务的数量大于1,那么就会开启子线程和当前线程一起并发执行block中的代码(任务)

操作队列的基本使用

  • NSInvocationOperation
    • 回顾GCD中的队列
      • 并发队列
        • 自己创建
        • 全局并发队列
      • 串行队列
        • 自己创建
        • 主队列
    • NSOperation队列
      • 主队列 mainQueue== GCD中串行队列中的主队列
        • 串行
        • 凡是在主队列中的任务都在主线程中执行
      • 非主队列 alloc]init
        • 默认情况下是并发队列
        • 可以设置为串行队列(最大并发数)
        • 可以开多条线程,并发执行任务
    • 基本使用
      • 创建一个非主队列alloc]init
      • 封装操作NSInvocationOperation alloc]initWithTarget:selector:object:
      • 添加操作到队列中addOperation
      • 为什么不调用start方法也能执行操作呢?因为addOperation内部会调用start方法】
  • NSBlockOperation
    • 创建队列alloc]init
    • 封装操作blockOperationWithBlock:
    • 添加操作到队列中 addOperation
    • 并发执行任务的
    • 追加任务 addExecutionBlock:^{}
    • 简便方法
      • queue addOperationWithBlock:^{}
      • 内部做了两件事情
        • 创建操作
        • 把操作添加到队列
      • 缺点:拿不到操作对象,无法设置操作

NSOperation属性

  • 最大并发数(默认是-1)

    • 创建队列
    • 封装操作
    • 添加操作到队列中
    • 要求:按顺序执行任务,改为串行队列
      • 设置最大并发数(同一时间最多可以执行的任务的数量)maxConcurrentOperationCount = 1
      • 设置最大并发数的时候,要保证一个操作里面就有一个任务
        • 追加任务,最大并发数没有用了,因为追加任务大于1的时候,会自动开子线程,并发执行任务
      • 最大并发数不能设置为0,一般设置为5~6
      • 默认是-1,-1是指数量不受限制
  • suspended暂停任务

    • 创建队列
    • 封装操作
    • 设置最大并发数 = 1(便于观察suspend)
    • 添加操作到队列中
      • 注意点:开几条线程不是有操作数量决定的
      • suspended是BOOL类型
      • 定义一个队列属性
      • storyboard中添加控件
        • 开始
        • 暂停
          • setSuspended:YES
          • 没有立刻停住,操作是原子性的,block里的任务是一个整体,只要开始就停不下来,暂停是针对操作来说的
          • 暂停操作,只能暂停后面尚未执行的操作,对于当前处于执行状态的任务是没有影响的
        • 恢复
          • setSuspended:NO
        • 取消
          • cancelAllOperations队列里的所有的操作都会调用cancel方法
          • 取消之后,就不能恢复了
          • 取消操作只能取消后面尚未执行的操作,对于当前处于执行状态的任务是没有影响的

自定义操作

  • 新建一个继承自NSOperation的类
  • 创建队列
  • 封装操作
    • 敲不出来alloc]initWithTarget: 和blockOperationWithBlock:
    • 只能用alloc]init
    • main方法里面封装操作,自定义的类里面重写main方法
  • 把操作添加到队列里面去
    • addOperation
  • 好处:
    • 能够提高代码的复用性,把代码放到main方法里
    • 信息隐蔽
  • 问题:
    • 不会马上取消
    • 产生原因
      • 三个for循环是一个整体,是同一个操作,是没有办法取消的
      • 拿到队列里的所有操作,调用cancel方法
    • 解决:每当执行完一个耗时操作之后,就检查当前的操作是否已经被取消,如果已经取消那么久结束任务
if(self.isCancelled){
    return;
}
- 怎么达到点击取消,立刻就取消,把判断方法放到for循环里面,但是性能不好,不推荐使用

操作队列中的依赖和监听(掌握)

  • 创建队列alloc]init
  • 添加三个操作
    • NSBlockOperation blockOperatinoWithBlock:
  • 怎么实现类似GCD栅栏函数,队列组功能?
    • 三个操作执行完毕后,执行任务4
    • 设置依赖
      • 任务4 addDependency 任务1
      • 任务4 addDependency 任务2
      • 任务4 addDependency 任务3
    • 可以设置多重依赖(按照4321的顺序执行)
      • 任务1 addDependency 任务2
      • 任务2 addDependency 任务3
      • 任务3 addDependency 任务4
    • 注意:不能设置循环依赖
    • 如果有多个队列,可以实现跨队列依赖
      • 任务5添加到第二个队列中
      • 可以让任务4依赖于任务5
    • 设置监听
      • .completionBlock = ^{}
  • 添加操作到队列
    • addOperation

线程间通信

  • 下载图片在子线程,回到主线程刷新UI
  • 创建队列 alloc]init
  • 封装操作
    • NSBlockOperation blockOperationWithBlock:
    • 确定URL
    • 把图片的二进制数据下载到本地
    • 转换格式
  • 添加操作到队列
    • addOperation
    • 添加到队列之后,才会回过头来执行上面的block块
  • 回到主线程设置图片
    • 方式一:可以混合使用GCD
    • 方式二:
NSOperationQueue mainQueue]addOperationWithBlock:^{
  self.imageV.image = image ;
    }    
  • 修改配置文件

  • 怎么使用操作队列下载两张图片合成一张图片?

GCD和NSOperation对比

  • GCD是纯C语言的API,而操作队列则是OC的对象
  • 在GCD中任务用block块来表示,而block块是一个轻量级的数据结构;相反操作队列中的操作NSOperation对象则是一个更加重量级的OC对象
  • 开发中使用GCD还是NSOperation需要看具体的情况
    • 看个人喜好,一般而言,实现同一种功能,采用封装程度更高的NSOperation
    • 如果开发中,只是简单的开线程执行任务,可以使用GCD
    • 如果处理多个任务,并且有依赖关系,可以使用NSOperation

NSOperation和NSOperationQueue的好处

  • NSOperationQueue可以方便的调用cancel方法来取消某一个操作,而GCD中的任务是无法被取消的(安排好任务之后就不管了)
  • NSOperation可以方便的指定操作间的依赖关系
  • NSOperation可以通过KVO提供对NSOperation对象的精细控制(如监听当前操作是否被取消或是否已经完成)
    • cancelld finished
    • 注册添加监听
      • download addObserver:options:旧值还是新值 context:
    • 调用方法observerValueForKeyPath:ofObject:change:context:
  • NSOperation可以方便的指定操作的优先级,操作优先级表示此操作与队列中的其他操作之间的优先关系,优先级高的操作先执行,优先级低的后执行
  • 通过自定义NSOperation的子类可以实现操作重用

相关文章

网友评论

      本文标题:NSOperation

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