NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象,是一套Object-C的API
GCD提供了更加底层的控制,而操作队列则在GCD之上实现了一些方便的功能,这些功能对于开发者而言通常是最好且最安全的选择。
NSOperationQueue有两种不同类型的队列:主队列和自定义队列
主队列运行在主线程上
自定义队列在后台(子线程)执行
队列处理的任务是NSOperation的子类:NSInvocationOperation和NSBlockOperation
NSOperation的基本使用步骤:
1,定义操作队列
2,定义操作(任务)
3,将操作(任务)添加到队列
注意:一旦将任务添加到队列,任务就会立即被调度执行。
NSOperation小结:
从本质上来看,操作队列的性能会比GCD略低,不过,大多数情况下,这点负面影响可以忽略不计,操作队列是并发变成的首选
下面这段代码是对 主队列、自定义队列、操作(任务)的创建、控制任务的执行顺序、控制自定义队列中开辟线程的数量 的一个演示:
//
// JLViewController.m
// 02-NSOperation
//
// Created by Mac on 15-4-3.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLViewController.h"
@interface JLViewController ()
/**
* 自定义队列
*/
@property (nonatomic, strong)NSOperationQueue *myQueue;
@end
@implementation JLViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myQueue = [[NSOperationQueue alloc] init];
// [self operationQueue_Demo1];
// [self operationQueue_Demo2];
// [self operationQueue_Demo3];
[self operationQueue_Demo4];
}
/**
* 模拟从网络获取图片,并显示图片的过程
*/
- (void)operationQueue_Demo4{
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"修饰图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"保存图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新UI %@", [NSThread currentThread]);
}];
// 设定执行顺序, Dependency:依赖
// 依赖关系是可以跨队列的!如果不设置依赖关系,相当于是一个并行的队列(没有执行顺序)。
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// 设置并发的线程数量,也就是设置自定义队列中允许开辟的子线程的数量
[self.myQueue setMaxConcurrentOperationCount:2];
// 将创建的任务添加到自定义队列,自定义队列都是在子线程中执行的
[self.myQueue addOperation:op1];
[self.myQueue addOperation:op2];
[self.myQueue addOperation:op3];
// 所有UI的更新需要在主线程上进行
[[NSOperationQueue mainQueue] addOperation:op4];
// 因为我们在代码中设置了各个任务之间的依赖关系,所以会先执行顺序为op1 -> op2 -> op3 -> op4
// 其中op1,op2,op3是在子线程中执行的,而op4是在主线程中执行的。
}
/**
* 创建任务(NSInvocationOperation)
使用这种方式创建任务,需要准备一个被调用的方法,并且能够接收一个参数。
*/
- (void)operationQueue_Demo3{
NSInvocationOperation *invo = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invoOperation:) object:@"hello world"];
// [self.myQueue addOperation:invo];
[[NSOperationQueue mainQueue] addOperation:invo];
}
- (void)invoOperation:(NSString *)str{
NSLog(@"%@", str);
}
/**
* 主队列
*/
- (void)operationQueue_Demo2{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
// 打印结果:{name = (null), num = 1}
// num = 1表示是在主线程(主队列)中执行
}
/**
* 创建任务(NSBlockOperation)
*/
- (void)operationQueue_Demo1{
// 创建任务
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
[self.myQueue addOperation:block];
// 打印结果:{name = (null), num = 2}
// num = 2表示子线程,所有自定义队列都是在子线程中执行的
// 以上代码可以简写成:
// [self.myQueue addOperationWithBlock:^{
// NSLog(@"%@", [NSThread currentThread]);
// }];
}
@end