NSOperation和NSOperationQueue

2019-02-12  本文已影响0人  愤怒的八哥

NSOperation

NSOperation 是个抽象类,不能用来封装操作。我们只有使用它的子类来封装操作。我们有三种方式来封装操作。
1、使用子类 NSInvocationOperation
2、使用子类 NSBlockOperation
3、自定义继承自 NSOperation 的子类,通过实现内部相应的方法来封装操作。
在不使用 NSOperationQueue,单独使用 NSOperation 的情况下系统同步执行操作,
注意
1、在其他线程中单独使用子类 NSInvocationOperation,操作是在当前调用的其他线程执行的,并没有开启新线程。
2、
NSBlockOperation 执行一个操作的情况下,操作是在当前线程执行的,并没有开启新线程。
NSBlockOperation 还提供了一个方法 addExecutionBlock:,通过 addExecutionBlock: 就可以为 NSBlockOperation 添加额外的操作。这些操作(包括blockOperationWithBlock中的操作)可以在不同的线程中同时(并发)执行。只有当所有相关的操作已经完成执行时,才视为完成。
如果NSBlockOperation已经执行结束或正在执行,addExecutionBlock就会崩溃
The block should take no parameters and have no return value.
3、自定义继承自 NSOperation 的子类

重写main方法,main 执行完返回的时候,这个操作就结束了。如果需要复用,就要让runloop一直存活下去。
类型 API 说明
取消 - (void)cancel; 实质是标记 isCancelled 状态
判断操作状态方法 - (BOOL)isFinished; 判断操作是否已经结束
- (BOOL)isCancelled; 判断操作是否已经标记为取消
- (BOOL)isExecuting; 判断操作是否正在在运行
- (BOOL)isReady; 判断操作是否处于准备就绪状态,这个值和操作的依赖关系相关
操作同步 - (void)waitUntilFinished; 阻塞当前线程,直到该操作结束。可用于线程执行顺序的同步
添加操作 - (void)setCompletionBlock:(void (^)(void))block; completionBlock 会在当前操作执行完毕时执行 completionBlock

NSOperationQueue

类;型 API 说明
主队列 mainQueue 凡是添加到主队列中的操作,都会放到主线程中执行(注:不包括操作使用addExecutionBlock:添加的额外操作,额外操作可能在其他线程执行)
队列并发数控制 maxConcurrentOperationCount 控制的不是并发线程的数量,而是一个队列中同时能并发执行的最大操作数。而且一个操作也并非只能在一个线程中运行。开启线程数量是由系统决定的,不需要我们来管理
maxConcurrentOperationCount = 1 并发数为1,串行执行
maxConcurrentOperationCount 大于1或者为 -1 并发执行

方法说明:

类型 API 说明
取消 - (void)cancelAllOperations; 可以取消队列的所有操作
判断操作状态方法 - (BOOL)isSuspended; 判断队列是否处于暂停状态。 YES 为暂停状态,NO 为恢复状态
- (void)setSuspended:(BOOL) 可设置操作的暂停和恢复,YES 代表暂停队列,NO 代表恢复队列
操作同步 - (void)waitUntilAllOperationsAreFinished; 阻塞当前线程,直到队列中的操作全部执行完毕
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; 向队列中添加操作数组,wait 标志是否阻塞当前线程直到所有操作结束
获取队列 + (id)currentQueue; 当前队列
+ (id)mainQueue; 主队列

二者结合使用步骤

1、创建操作:先将需要执行的操作封装到一个 NSOperation 对象中。
2、创建队列:创建 NSOperationQueue 对象。
3、将操作加入到队列中:将 NSOperation 对象添加到NSOperationQueue 对象中。
之后,系统就会自动将 NSOperationQueue 中的 NSOperation 取出来,在新线程中执行操作。


使用注意点

操作在队列中的执行顺序

1、操作就绪
当一个操作的所有依赖都已经完成时,操作对象通常会进入准备就绪状态,等待执行。
2、操作优先级(queuePriority)
对于添加到队列中的操作,首先进入准备就绪的状态(就绪状态取决于操作之间的依赖关系),然后进入就绪状态的操作的开始执行顺序(非结束执行顺序)由操作之间相对的优先级决定(优先级是操作对象自身的属性)。

3、操作之间的依赖关系

- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;

通过添加操作依赖,可以使操作顺序有序。如操作A依赖操作B,那么在队列中,永远是操作B先执行,然后才执行操作B。
二者关系总结:
如果一个队列中既包含高优先级操作,又包含低优先级操作,并且两个操作都已经准备就绪,那么队列先执行高优先级操作。
如果一个队列中既包含了准备就绪状态的操作,又包含了未准备就绪的操作,未准备就绪的操作优先级比准备就绪的操作优先级高。那么,虽然准备就绪的操作优先级低,也会优先执行。优先级不能取代依赖关系。如果要控制操作间的启动顺序,则必须使用依赖关系。


参考
https://www.jianshu.com/p/4b1d77054b35

上一篇下一篇

猜你喜欢

热点阅读