简介
NSOpreation的作用
p 配合NSOperation和NSOperationQueue也能够实现多线程编程NSOperation 和 NSOperationQueue实现多线程的具体步骤
p 先将需要执行的操作封装到一个NSOperation对象中
p 然后将NSOperation对象添加到NSOperationQueue队列中
p 系统会自动将NSOperationQueue中的NSOperation取出来
p 将取出的NSOperation封装的操作放到一条新线程中执行
NSOpreation的子类
NSOpreation是个抽象类,并不具备封装操作的能力,
使用NSOperation子类的方式有3种
pNSInvocationOperation
pNSBlockOperation
p 自定义子类继承NSOperation,实现内部相应的方法。
NSInvocationOperation
- 创建NSInvocationOperation对象
NSInvocationOperation *p =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
- 调用start方法开始执行操作
-(void)start
//一旦执行就会调用target的sel方法
- 注意
p 默认情况下,调用了start方法后并不会开启一条新线程去执行操作,而是在当前线程同步执行操作
p 只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:p];
NSBlockOperation
- 创建NSBlockOperation对象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
//在主线程中执行
NSLog(@"%@",[NSThread currentThread]);
}];
- 通过
- (void)addExecutionBlock:(void (^)(void))block;
方法添加更多的操作
//添加额外的任务(在子线程执行)
[op addExecutionBlock:^{
NSLog(@"----%@",[NSThread currentThread]);
}];
[op start];
- 注意: 只要NSBlockOperation封装的操作数大于1 ,就会异步执行操作
NSOperationQueue
- NSOperationQueue的作用
p NSOperation可以调用start方法来执行任务,但默认是同步执行的
p 如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作 - 添加操作到NSoperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;
- (对比GCD)
- GCD的队列类型
- 并发队列
- 自己创建的
- 全局的
- 串行队列
- 主队列
- 自己创建的
- 并发队列
- NSOperationQueue的队列类型
- 主队列
- [NSoperationQueue mainQueue]
- 凡是添加到主队列中的任务,都会放到主线程中执行
- 非主队列(其他队列)
- [[NSOperationQueue alloc] init]
- 同时包含了串行、并行功能
- 添加到这种队列中的任务(NSOperation),就会被自动放到子线程中执行
- 示例代码
- (void)OperationQueue{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//创建操作(任务)
//创建NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];
//创建NSBlockOperation
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"task3 ---- %@",[NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"task4 ---- %@",[NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"task5 ---- %@",[NSThread currentThread]);
}];
[queue addOperation:op1];//内部会自动调 [op1 start];
[queue addOperation:op2];//内部会自动调 [op2 start];
[queue addOperation:op3];//内部会自动调 [op3 start];
}
- (void)task1{
NSLog(@"task1----%@",[NSThread currentThread]);
}
- (void)task2{
NSLog(@"task2----%@",[NSThread currentThread]);
}
- 自定NSOperation
p 可以创建一个继承自NSOperation的类,在类的.m文件中重写方法- (void)main;
将需要执行的任务写在main方法中,然后 创建队列,实例化自定义类,将实例添加到队列中,也可以开启新线程执行任务。
p 示例代码
- (void)lgjOperation{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//创建自定义NSOperationQueue
LGJNSOperation *operation = [[LGJNSOperation alloc] init];
[queue addOperation:operation];//[operation start];
}
//自定义Operation类
//.h文件
#import <Foundation/Foundation.h>
@interface LGJNSOperation : NSOperation
@end
//.m文件
#import "LGJNSOperation.h"
@implementation LGJNSOperation
//
-(void)main{
NSLog(@"LGJNSOperation -- 下载图片---%@",[NSThread currentThread]);
}
@end
最大并发数
什么是并发数
p 同时执行的任务数
p 比如同时开三个线程,执行三个任务,最大并发数就是3-
最大并发数的相关方法
- (NSInteger)maxConcurrentOperationCount; - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
p 示例代码
//最大并发数
- (void)OperationQueue1{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//设置最大并发数
//queue.maxConcurrentOperationCount = 2;
queue.maxConcurrentOperationCount = 1;//变成了串行队列
[queue addOperationWithBlock:^{
NSLog(@"task1---%@",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"task2---%@",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"task3---%@",[NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"task4---%@",[NSThread currentThread]);
}];
}
队列的取消、暂停、恢复
- 取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作
- 暂停和恢复队列
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended;
-示例代码1
- (void)viewDidLoad {
[super viewDidLoad];
[self OperationQueue];
}
-(void)OperationQueue{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;//设置为1就变成了串行队列
//当执行了[self.queue cancelAllOperations];已经开启的线程是刹不住车的(意思是会继续打印),没有开启的线程将不会开启
[queue addOperationWithBlock:^{
for (NSInteger i = 0; i<1000 ; i++) {
NSLog(@"task1 - %zd- %@",i,[NSThread currentThread]);
}
}];
[queue addOperationWithBlock:^{
for (NSInteger i = 0; i<1000 ; i++) {
NSLog(@"task2 - %zd- %@",i,[NSThread currentThread]);
}
}];
[queue addOperationWithBlock:^{
for (NSInteger i = 0; i<1000 ; i++) {
NSLog(@"task3 - %zd- %@",i,[NSThread currentThread]);
}
}];
self.queue = queue;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.queue cancelAllOperations];
}
- 示例代码2
#import "ViewController.h"
#import "LGJOperation.h"
@interface ViewController ()
@property(nonatomic,strong)NSOperationQueue *queue;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self OperationQueue];
}
-(void)OperationQueue{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;//设置为1就变成了串行队列
//开启一条线程 执行自定义operation任务,任务的具体内容封装在自定义类的main方法中
LGJOperation *op = [[LGJOperation alloc] init];
[queue addOperation:op];
self.queue = queue;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.queue cancelAllOperations];
}
//自定义operation
.h文件
#import <Foundation/Foundation.h>
@interface LGJOperation : NSOperation
@end
//.m文件
#import "LGJOperation.h"
@implementation LGJOperation
-(void)main{
for (NSInteger i = 0; i<5000 ; i++) {
//也可以在这里终止
if (i == 4000) {
if (self.cancelled) return;
}
NSLog(@"task1 - %zd- %@",i,[NSThread currentThread]);
}
//如果想要终止线程中的任务,需要人为的做判断
if (self.cancelled) return;
for (NSInteger i = 0; i<1000 ; i++) {
NSLog(@"task2 - %zd- %@",i,[NSThread currentThread]);
}
//可以在这里终止
if (self.cancelled) return;
for (NSInteger i = 0; i<1000 ; i++) {
NSLog(@"task3 - %zd- %@",i,[NSThread currentThread]);
}
}
@end
- 示例代码2
- (void)viewDidLoad {
[super viewDidLoad];
[self suspended];
}
//
- (void)suspended{
//创建队列
self.queue1 =[[NSOperationQueue alloc] init];
//设置最大并发数
self.queue1.maxConcurrentOperationCount = 1;
[self.queue1 addOperationWithBlock:^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"task1----%@",[NSThread currentThread]);
}];
[self.queue1 addOperationWithBlock:^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"task2----%@",[NSThread currentThread]);
}];
[self.queue1 addOperationWithBlock:^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"task3----%@",[NSThread currentThread]);
}];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if (self.queue1.isSuspended) {
//恢复队列,继续执行
self.queue1.suspended = NO;
}else{
// 暂停(挂起)队列,暂停执行
self.queue1.suspended = YES;
}
}
操作依赖
NSOperation之间可以设置依赖来保证执行顺序
p 比如一定要让操作A执行完以后,才能执行操作B,可以这么写示例代码
- (void)viewDidLoad {
[super viewDidLoad];
[self Dependency];
}
//操作依赖
- (void)Dependency{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"1"];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"2"];
NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2:) object:@"3"];
//设置依赖
[operation1 addDependency:operation2];//1 依赖于 2
[operation2 addDependency:operation3];//2 依赖于 3
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
- (void)run2:(NSString*)obj{
NSLog(@"[current thread]==%@---obj===%@",[NSThread currentThread],obj);
}```
- 可以在不同queue的NSOperation之间创建依赖关系
![屏幕快照 2016-06-17 上午10.48.51.png](http://upload-images.jianshu.io/upload_images/1970936-3be6eb8e07440d13.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
######操作的监听
- 可以监听一个操作的执行完毕
```-objc
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block; ```
- 示例代码
```-objc
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"task1 === %@",[NSThread currentThread]);
}];
operation1.completionBlock = ^{
NSLog(@"监听任务一执行完没1");
};
// [operation1 setCompletionBlock:^{
//
// NSLog(@"监听任务一执行完没2");
// }];
[queue addOperation:operation1];