NSOperation

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的子类可以实现操作重用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容