iOS开发之NSOperationQueue
一. NSOperationQueue
- NSOperation是个抽象类,并不具备封装操作的能力,必须使用其子类
- NSInvocationOperation
- NSBlockOperation
- 自定义继承NSOperation
- 配合使用NSOperation和NSOperationQueue能实现多线程编程.
NSInvocationOperation
- (void)invocationOperation
{
//在当前线程中执行任务(主线程)
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
[operation start];
}
- (void)run
{
NSLog(@"------%@", [NSThread currentThread]);
}
//打印结果:
------{number = 1, name = main}
NSBlockOperation
- (void)blockOperation
{
NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^{
// 在主线程
NSLog(@"下载1------%@", [NSThread currentThread]);
}];
// 添加额外的任务(在子线程执行)
[operation addExecutionBlock:^{
NSLog(@"下载2------%@", [NSThread currentThread]);
}];
[operation start];
}
//
//下载一在主线程执行
下载1------{number = 1, name = main}
//下载二开启了新的线程 addExecutionBlock可以实现多线程异步操作
下载2------{number = 2, name = (null)}
NSOperationQueue
1.NSOperation可以调用start的方法来执行任务,但是默认同步执行.
2.如果把NSOperation加到NSOperationQueue(操作队列)中,系统就会自动异步执行NSOperation中的任务.
NSOperationQueue的队列类型
- 主队列
- 添加到主队列的任务都会在主线程执行
[NSOperationQueue mainQueue];
-
其他队列(串行,并行)
- 同时包含了串行和并行的功能.
- 添加到这种队列中的任务,都会自动放在子线程中执行.
[[NSOperationQueue alloc]init];
创建任务添加到队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//创建操作
//1.创建NSInvocationOperation任务
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
//2.创建NSBlockOperation任务
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test2---%@",[NSThread currentThread]);
}];
//3.创建自定义任务
RKOperation *operation3 = [[RKOperation alloc]init];
//4.队列添加Block任务
[queue addOperationWithBlock:^{
NSLog(@"test3---%@",[NSThread currentThread]);
}];
//添加到队列中,就执行了start的方法.
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
- 设置队列的最大并发数
queue.maxConcurrentOperationCount = 1;
当maxConcurrentOperationCount该队列的最大并发数,当maxConcurrentOperationCount = 1的时候,该队列就是串行队列,失去了并发功能.(queue就是通过这个属性来控制队列是串行还是并行).
- 队列的任务的挂起(suspended)和取消(cancle)
- 挂起(suspended)
当有任务在执行的时候,当前正在执行的任务是不能挂起的,只能等该任务完成后,队列中其他任务就会被挂起了.
- (void)viewDidLoad {
[super viewDidLoad];
self.queue = [[NSOperationQueue alloc]init];
[self.queue addOperationWithBlock:^{
for (int i = 0; i < 5000; i++) {
NSLog(@"download1 --- %d---%@",i,[NSThread currentThread]);
}
}];
[self.queue addOperationWithBlock:^{
for (int i = 0; i < 5000; i++) {
NSLog(@"download2 --- %d---%@",i,[NSThread currentThread]);
}
}];
[self.queue addOperationWithBlock:^{
for (int i = 0; i < 5000; i++) {
NSLog(@"download3 --- %d---%@",i,[NSThread currentThread]);
}
}];
[self.queue addOperationWithBlock:^{
for (int i = 0; i < 5000; i++) {
NSLog(@"download4 --- %d---%@",i,[NSThread currentThread]);
}
}];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if(self.queue.suspended){
self.queue.suspended = NO;
}else{
self.queue.suspended = YES;
}
}
```
- 取消
> 取消了就不能再次执行了,只能重新添加任务.
> 当有任务在执行的时候,当前任务是不能取消的,会正在执行的任务执行完毕.队列中的其他任务就在执行了.
[self.queue cancelAllOperations];
> 官方推荐自定义任务,在每个消耗时间的任务后都判断下cancle
#import "RKOperation.h"
@implementation RKOperation
//在mian函数中写需要执行的任务.
-(void)main{
for (int i = 0; i < 5000; i++) {
NSLog(@"download1 --- %d---%@",i,[NSThread currentThread]);
}
if (self.isCancelled) return;
for (int i = 0; i < 5000; i++) {
NSLog(@"download2 --- %d---%@",i,[NSThread currentThread]);
}
if (self.isCancelled) return;
for (int i = 0; i < 5000; i++) {
NSLog(@"download3 --- %d---%@",i,[NSThread currentThread]);
}
}
- 依赖
>添加依赖要在addOperation之前设置. 也可以跨队列设置依赖.
```
/// 添加依赖,是operation3必须在operation1和operation2完成后再可以进行
self.queue = [[NSOperationQueue alloc]init];
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test1---%@",[NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test2---%@",[NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test3---%@",[NSThread currentThread]);
}];
//添加依赖,是operation3必须在operation1和operation2完成后再可以进行
//添加依赖要在addOperation之前设置.
[operation3 addDependency:operation1];
[operation3 addDependency:operation2];
[self.queue addOperation:operation1];
[self.queue addOperation:operation2];
[self.queue addOperation:operation3];
- 线程间的通信
/**
* 线程之间的通信
*/
- (void)test
{
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
// 图片的网络路径
NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
// 加载图片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成图片
UIImage *image = [UIImage imageWithData:data];
// 回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];
}