一、NSOperationQueue简介

1.概述:
 NSOperationQueue类管理NSOperation对象的执行。NSOperationQueue可以被称为操作队列,NSOperation可以被称为操作。操作被添加到操作队列之后,操作队列会根据操作对象的优先级或者相互之间的依赖关系来执行操作。一个应用程序可以创建多个操作队列,每个操作队列分别管理若干操作。
2.什么时候操作会被移除:
 当操作被添加到队列中以后,我们不能从操作队列中直接移除操作对象。当一个操作对象的任务完成之后才会被自动移除。任务完成的含义:操作的start方法被调用,并且isFinished方法返回YES。
3.如何取消任务执行:
调用操作对象cancel方法并不能使操作马上停止执行。当NSOperation的cancel方法被调用后,如果操作不在队列中,这个方法会将操作的isFinished设为YES,如果在操作队列中,这个方法会将操作对象的isCancelled状态设为YES,并且isReady设为YES,让队列调用它的start方法。在start或者main方法实现中,我们应该检查isCancelled和isFinished属性,如果任意一个为YES,就不执行操作,直接返回,如果是并发操作,让isFinished方法返回YES,如果是非并发操作,设置isFinished值为YES。
4.操作队列的相关API:
(1)创建队列:
可以调用[[NSOperationQueue alloc] init]方法新建一个操作队列,或者调用类方法currentQueue、mainQueue方法获取现存的操作队列。currentQueue一般在NSOperation对象子类中调用,用来返回启动当前操作的队列,如果NSOperation在非运行状态或者在NSOperation外部调用此方法,一般会返回nil。mainQueue方法返回和主线程绑定的操作队列。
(2)增加操作:
addOperation:  增加一个操作对象。
addOperations:waitUntilFinished: 增加一个操作对象数组,可以阻塞当前线程等待所有操作完成。
addOperationWithBlock: 以block的方式添加操作,blcok必须为无参数无返回数据。
(3)最大并发数:
maxConcurrentOperationCount :最大并发数属性,默认为-1,表示并发数无限制,由系统根据环境条件动态决定。
setMaxConcurrentOperationCount:设置最大并发数。
(4)其它:
operations :获取添加到队列中的所有操作对象。
operationCount :获取添加到队列中的操作对象的数量。
setSuspended: 设置队列是否暂停安排操作执行。
isSuspended :获取队列是否处在暂停安排操作执行的状态。
cancelAllOperations:调用所有操作对象的cancel方法。
waitUntilAllOperationsAreFinished:阻塞当前线程,等待所有操作都完成。
5.KVO兼容的属性
operations - 只读
operationCount - 只读
maxConcurrentOperationCount - 可读写
suspended - 可读写
name -可读写
6.内部实现:
 在iOS4.0及以后,NSOperationQueue内部实现使用GCD,iOS4.0之前,使用NSThread实现。
二、NSOperation简介
1.概述:
NSOperation类代表单个任务对象,是一个抽象类,因此他不能直接使用它,可以实现它的子类,也可以使用类库中已存在的子类,比如NSInvocationOperation和NSBlockOperation,可以比较简单的创建操作对象。操作对象只能被执行一次,只要被执行过,就不能再重新执行第二次。
2.依赖关系:
(1)调用NSOperation的addDependency或者removeDependency可以给一个操作对象添加一个它所依赖的操作对象、删除一个所依赖的操作对象。调用dependencies方法可以获取一个操作所依赖的所有操作对象。
(2)只有当一个操作对象的所有依赖对象都执行完毕后,它的isReady属性才可能会成为YES,从而被队列执行。
(3)NSOperation本身并不区分它的依赖对象是执行失败还是成功,只判断操作是否执行完毕(即有可能是通过cancel方法完成的)。
(4)如果一个操作对象被调用了cancel方法,但是还有它依赖的操作对象没有完成,它所依赖的操作对象将被忽略,当前操作对象不再等待它们完成。
3.执行优先级
(1)调用queuePriority、setQueuePriority:方法可以获取和设置操作对象的执行优先级。
(2)类库中定义了几个优先级变量:
   NSOperationQueuePriorityVeryLow
   NSOperationQueuePriorityLow
   NSOperationQueuePriorityNormal
   NSOperationQueuePriorityHigh
   NSOperationQueuePriorityVeryHigh
   最高对应的数字为8,最低-8,如果手动设置数字,setQueuePriority方法会自动切换成对应的最合适的数字。
(3)优先级只表示此操作对象的优先级和其它对象优先级的大小关系,不能精确定义两个对象的执行顺序,不能使用优先级这个方式来实现依赖关系。
4.KVO兼容的属性
isCancelled - 只读,操作是不是被取消,cancel方法会改变此变量。
isConcurrent - 只读,是不是并发
isExecuting - 只读,是不是正在执行
isFinished - 只读,是不是已经完成
isReady - 只读,是不是已经准备好执行
dependencies - 只读,操作对象的依赖关系
queuePriority - 可读写,操作对象在队列中的优先级
completionBlock - 可读写,操作完成之后执行的Block
5.并发操作和非并发操作
(1)如果打算手动执行操作对象,我们可以把操作对象设计成非并发的,也可以涉及成并发的。操作对象默认是非并发的。
(2)在非并发的操作对象中,操作任务是以同步的方式实现的,当调用start方法时,任务在当前线程执行,当start方法返回时,任务已经完成,执行期间线程被阻塞。
(3)并发操作对象的任务以异步的方式执行,当调用start方法时,start方法立即返回,不阻塞当前线程。因为在start方法中,任务代码使用新线程或者异步API实现。
(4)如果打算总是以队列的方式执行操作,最简单的方式是将操作对象设计成非并发的。定义并发操作对象需要更过的工作,因为实现并发操作对象需要实现更多的方法,而且我们必须去监听任务的状态以及使用KVO手动通知的方式报告状态。当非并发操作在队列中执行时,队列会自动建立新线程来执行操作,最后结果也是异步的。所以如果总是以队列的方式执行操作对象,是没有理由使用并发操作的。
6.子类化NSOperation
(1)如果是非并发操作,只需要实现main方法即可。
(2)如果是并发操作,最少要实现一下四个方法:start、isConcurrent、isExecuting、isFinished。
(3)在main方法和start方法实现中,在开始执行任务代码前,首先应该检查对象状态,如果
isCancelled等于YES或者isFinished等于YES,则不用执行任务代码。如果是并发操作,让isFinished方法返回YES,如果是非并发操作,设置isFinished值为YES。
(4)在重写isConcurrent、isExecuting、isFinished方法的同时,还要对值发生改变的key使用KVO手动的方式触发通知,否则操作不会被认为执行结束。代码逻辑:在以上三个方法中通过判断本地的状态标记变量来判断状态值,并返回;在更改我们的本地标记变量值时,通过KVO发送通知,然后OperationQueue就会去调用以上三个方法来判断Operation执行状态,如果isFinished方法返回YES,则操作完成,任务结束。
7.异步NSOperation实现示例:

typedef enum

{

RequestStateReady = 0,

RequestStateExecuting,

RequestStateFinished

}RequestState;

@interface RequestOperation ()

@property(nonatomic,strong) NSURLConnection *connection;

@property(nonatomic,strong) NSMutableData *resultData;

@property(nonatomic,assign) RequestState requestState;

@end

@implementation RequestOperation

-(id)init{

self = [super init];

if (self) {

[self willChangeValueForKey:@"isReady"];

self.requestState = RequestStateReady;

[self didChangeValueForKey:@"isReady"];

}

return self;

}

#pragma mark - Operation实现父类方法

-(void)start{

[self exeRequest];

}

-(BOOL)isConcurrent{

return YES;

}

-(BOOL)isReady{

return self.requestState == RequestStateReady && [super isReady];

}

-(BOOL)isExecuting{

return self.requestState == RequestStateExecuting;

}

-(BOOL)isFinished{

return self.requestState == RequestStateFinished;

}

#pragma mark - 发起请求

-(void)exeRequest{

if (self.isCancelled == YES || self.isFinished == YES) {

return;

}

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.baidu.com/"]];

self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

[self.connection start];

[[NSRunLoop currentRunLoop] run];

[self willChangeValueForKey:@"isExecuting"];

self.requestState = RequestStateExecuting;

[self didChangeValueForKey:@"isExecuting"];

}

#pragma mark - 请求代理实现

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{

self.resultData = [[NSMutableData alloc] initWithCapacity:0];

}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{

[self.resultData appendData:data];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection{

[self willChangeValueForKey:@"isFinished"];

self.requestState = RequestStateFinished;

[self didChangeValueForKey:@"isFinished"];

}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{

[self willChangeValueForKey:@"isFinished"];

self.requestState = RequestStateFinished;

[self didChangeValueForKey:@"isFinished"];

}

@end

NSOperationQueue简介相关推荐

  1. iOS多线程:『NSOperation、NSOperationQueue』详尽总结

    2019独角兽企业重金招聘Python工程师标准>>> iOS多线程:『NSOperation.NSOperationQueue』详尽总结 转载: 原地址https://www.ji ...

  2. 多线程编程3 - NSOperationQueue

    一.简介 一个NSOperation对象可以通过调用start方法来执行任务,默认是同步执行的.也可以将NSOperation添加到一个NSOperationQueue(操作队列)中去执行,而且是异步 ...

  3. iOS 高大上函数响应式编程框架ReactiveCocoa学习笔记1 简介

    ReactiveCocoa函数响应式编程 一.简介 ReactiveCocoa(其简称为RAC)是函数响应式编程框架.RAC具有函数式编程和响应式编程的特性.它主要吸取了.Net的 Reactive ...

  4. etcd 笔记(01)— etcd 简介、特点、应用场景、常用术语、分布式 CAP 理论、分布式原理

    1. etcd 简介 etcd 官网定义: A highly-available key value store for shared configuration and service discov ...

  5. Docker学习(一)-----Docker简介与安装

    一.Docker介绍 1.1什么是docker Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源 Docker可以让开发者打包他们的应用以及依赖包到一个轻量级,可移植 ...

  6. 【Spring】框架简介

    [Spring]框架简介 Spring是什么 Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IOC(Inverse Of Control:反转控制)和AOP(Asp ...

  7. TensorRT简介

    TensorRT 介绍 引用:https://arleyzhang.github.io/articles/7f4b25ce/ 1 简介 TensorRT是一个高性能的深度学习推理(Inference) ...

  8. 谷粒商城学习笔记——第一期:项目简介

    一.项目简介 1. 项目背景 市面上有5种常见的电商模式 B2B.B2C.C2B.C2C.O2O B2B 模式(Business to Business),是指商家和商家建立的商业关系.如阿里巴巴 B ...

  9. 通俗易懂的Go协程的引入及GMP模型简介

    本文根据Golang深入理解GPM模型加之自己的理解整理而来 Go协程的引入及GMP模型 一.协程的由来 1. 单进程操作系统 2. 多线程/多进程操作系统 3. 引入协程 二.golang对协程的处 ...

最新文章

  1. Node.js in IIS — Hello World
  2. 如何设置Reporting Services链接到网页URL的参数?
  3. andengine游戏引擎总结基础篇
  4. 脑洞大开的机器视觉多领域学习模型结构 | CVPR 2018论文解读
  5. Fiori offline support : overrideRefreshHandling and injectRefreshList
  6. 英语口语 week11 Friday
  7. strace调试(Linux Device Driver)
  8. leetcode - 213. 打家劫舍 II
  9. jqurey ajax 的动态添加二级联动下拉菜单
  10. Arduino ISP下载接口
  11. 软件工程复习之rup
  12. 谷歌地图网页版_如何在网站嵌入谷歌地图
  13. 智能网联汽车OTA升级安全设计
  14. 这次的新计算,很全能!
  15. node下载文件 解压压缩包
  16. freeswitch通过limit限制cps
  17. 研究生发论文的流程?
  18. 如果一份工作让你时常感到焦虑,你会不会立马辞职?
  19. CP Editor安装配置
  20. Android仿头条频道管理

热门文章

  1. Python+selenium第一个自动化脚本
  2. Openstack Havana的两个排错过程
  3. Ubuntu桌面培训(Ubuntu Desktop Course)中文译本发布
  4. 数据结构与算法——哈希表与字符串
  5. Unity3D-InstantOC遮挡剔除
  6. vb.net读取excel并写入dgv_读取PDF中的表格写入EXCEL?30行代码搞定
  7. linux非权限安装bioperl,Bioperl的简单安装
  8. matlab编程实现二进制树搜索,数据结构: 二进制搜索树(用C语言实现)
  9. java游戏应龙女魃转世_应龙和女魃的凄美爱情,究竟是爱情,还是阴谋?
  10. 判断表达式值是否为空_如何在 Python 中判断列表是否为空