一、概述
NSOperation、NSOperationQueue是基于GCD的一层封装。相对于GCD来说,NSOperation、NSOperationQueue可以设置线程依赖、执行顺序、暂停取消执行、设置最大并发数、KVO监听操作状态的改变等操作。
二、操作、操作队列
NSOperation、NSOperationQueue是基于GCD的封装,使用方法基本类似,也是存在操作、队列。
1.操作
通过使用NSOperation的子类:NSInvocationOperation、NSBlockOperation,或者自定义子类来封装要执行的任务。
2.队列
NSOperationQueue 对于添加到队列中的操作,首先进入准备就绪的状态,然后开始执行顺序。操作队列通过设置最大并发操作数来控制并发、串行。NSOperationQueue 提供了两种不同类型的队列:主队列和自定义队列。主队列运行在主线程之上,而自定义队列在子线程执行。
3.使用方法
NSOperation、NSOperationQueue是搭配使用才能达到多线程的功能。只是用NSOperation是在主线程中同步操作(使用步骤大致与GCD一样)。
步骤:
(1)创建操作:把要执行的任务添加到NSOperation对象中
(2)创建队列:创建NSOperationQueue对象
(3)操作添加到队列:把NSOperation对象添加到NSOperationQueue对象中
三、具体的使用方法
1.NSOperation
NSOperation是抽象类,只能子类化来使用。有三种方法来封装操作:
(1)使用子类 NSInvocationOperation
(2)使用子类 NSBlockOperation
(3)自定义继承自 NSOperation 的子类,通过实现内部相应的方法来封装操作。
1.1 子类 NSInvocationOperation
// 1.创建 NSInvocationOperation 对象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doIt) object:nil];
// 2.调用 start 方法开始执行操作
[op start];
//3.实现任务
- (void)doIt{
//要执行的任务};
1.2子类 NSBlockOperation
// 1.创建 NSBlockOperation 对象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
//要执行的任务;
}
}];
// 2.调用 start 方法开始执行操作
[op start];
// 3.添加额外的操作
[op addExecutionBlock:^{
//可以添加额外的任务
}];
1.3自定义继承自 NSOperation 的子类
自定义继承自 NSOperation 的子类。通过重写 main 或者 start 方法实现自己的 NSOperation 对象。重写main方法我们不需要管理操作的状态属性 isExecuting 和 isFinished。当 main 执行完,这个操作就结束了。
//1.自定义继承NSOperation的子类
@interface AAOperation : NSOperation
@end
@implementation AAOperation
- (void)main {
//要执行的任务
}
//2.在其他类中使用,导入头文件
- (void)userName:(NSString *)text{
// 1.创建 AAOperation 对象
AAOperation*op = [[AAOperationalloc] init];
// 2.调用 start 方法开始执行操作
[op start];
}
2.创建队列
NSOperationQueue分为:主队列、自定义队列。自定义队列有串行、并发。
2.1主队列
NSOperationQueue *queue = [NSOperationQueue mainQueue];
2.2自定义队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
2.3操作添加到队列
两种方法:
(1)- (void)addOperation:(NSOperation *)op;
需要先创建操作,再将创建好的操作加入到创建好的队列中去。开启新的线程
// 1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 创建操作
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doIt) object:nil];
// 3.添加操作到队列
[queue addOperation:op1];
(2)- (void)addOperationWithBlock:(void (^)(void))block;
无需创建操作,在 block 中添加操作,直接将包含操作的 block 加入到队列中。开启新的线程,并发执行
// 1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.使用 addOperationWithBlock: 添加操作到队列中
[queue addOperationWithBlock:^{
//执行的任务
}];
3.串行、并行的控制
关键属性 maxConcurrentOperationCount最大并发操作数。用来控制一个队列中可以有多少个操作同时参与并发执行。
maxConcurrentOperationCount 默认情况下为-1,表示不进行限制,可进行并发执行。
maxConcurrentOperationCount 为1时,串行队列,串行执行。
maxConcurrentOperationCount 大于1时,并发队列
四、依赖、优先级、暂停取消、监听
1.依赖方法:
- (void)addDependency:(NSOperation *)op; 添加依赖,使当前操作依赖于操作 op 的完成。
- (void)removeDependency:(NSOperation *)op; 移除依赖,取消当前操作对操作 op 的依赖。
@property (readonly, copy) NSArray<NSOperation *> *doItArray; 在当前操作开始执行之前完成执行的所有操作对象数组
2.优先级
NSOperation 提供了queuePriority(优先级)属性,queuePriority属性适用于同一操作队列中的操作,不适用于不同操作队列中的操作。
设置优先级:- (void)setQueuePriority:(NSOperationQueuePriority)p;
3.取消暂停
(1)取消队列的所有操作
- (void)cancelAllOperations;
注意:也可以调用NSOperation的- (void)cancel方法取消单个操作
(2)暂停和恢复队列
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended; //当前状态
4.监听
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;
//操作监听
op.completionBlock=^{
NSLog(@"3已经执行完了------%@",[NSThread currentThread]);
};
五、线程间通信
//回到主线程刷新UI
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
self.imageView.image=image;NSLog(@"刷新UI---%@",[NSThread currentThread]);
}];
网友评论