NSOperation 抽象类
- NSInvocationOperation
- NSBlockOperation
NSOpeartionQueue
* GCD 的核心概念:将任务(block)添加到队列,并且指定执行任务的函数
* OP 的核心概念:将`操作`添加到`队列`
NSInvocationOperation(不常用)
// 将操作添加到队列 - 会异步
执行操作!
- (void)opDemo1 {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"invocation"];
// start 会在当前线程执行 selector 方法,不会开启线程
// [op start];
// 队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 将操作添加到队列 - 会`异步`执行操作!
[queue addOperation:op];
}
队列是一个并发
队列
- (void)opDemo2 {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (int i = 0; i < 100; ++i) {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@(i)];
[queue addOperation:op];
}
}
- (void)demo:(id)obj {
NSLog(@"%@ %@", [NSThread currentThread], obj);
}
NSBlockOperation(常用)
任务在子线程异步并发执行
- (void)opDemo3 {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 操作
// 使用 block 所有的代码可以在一起,便于阅读和维护
for (int i = 0; i < 10; ++i) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
[queue addOperation:op];
}
}
将任务加入到一个全局队列, 并且NSOperation的所有子类都可以加入, 异步执行
- (void)opDemo4 {
for (int i = 0; i < 10; ++i) {
[self.queue addOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
// BLOCK OPERATION
// 所有的 NSOperation 的子类,都可以添加到队列中
// 并且都是异步执行的!
NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"BLOCK --- %@", [NSThread currentThread]);
}];
[self.queue addOperation:blockOp];
NSInvocationOperation *inOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"INVOCATION"];
[self.queue addOperation:inOp];
}
线程间通讯
- (void)opDemo5 {
[self.queue addOperationWithBlock:^{
NSLog(@"耗时的操作... %@", [NSThread currentThread]);
// 在主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"更新 UI %@", [NSThread currentThread]);
}];
}];
}
NSOperation的高级用法
- 最大并发数
- (void)demo {
// 设置最大并发的操作数
[self.queue setMaxConcurrentOperationCount:2];
NSLog(@"start");
for (int i = 0; i < 20; ++i) {
[self.queue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
}
// 执行结果是两个两个一起来
- 暂停/继续
// 暂停继续
- (IBAction)pauseAndResume {
// 如果队列是挂起的,再添加操作,也不会调度!
// 判断队列中是否有操作
if (self.queue.operationCount == 0) {
NSLog(@"没有操作");
return;
}
// setter = !getter
// 挂起的是队列,不会影响正在执行的操作
self.queue.suspended = !self.queue.isSuspended;
// 如果队列中的操作没有执行完成,操作`计数`中是包含的
if (self.queue.isSuspended) {
NSLog(@"暂停 - %tu", self.queue.operationCount);
} else {
NSLog(@"继续 - %tu", self.queue.operationCount);
}
}
执行结果: 暂停的是队列中的操作, 如果任务在线程中正在执行, 不会停止
- 取消全部
- (IBAction)cancelAll {
// 取消`队列`中没有调度的全部操作,如果正在执行的操作,不会被取消
// 提示:如果要让正在执行的操作取消,需要自定义操作,系统提供的不行!
NSLog(@"取消全部");
[self.queue cancelAllOperations];
}
执行结果: 系统提供的无法取消线程中正在执行的操作, 只能取消队列中等待的操作.
- 依赖关系(GCD中的依赖,可以用同步执行,barrier)
- (void)dependency {
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(@"通知用户 %@", [NSThread currentThread]);
}];
// 设置依赖关系 - 并发效率比GCD的串行队列要好!
// 依赖关系,可以跨队列指定!
// 付费需要在用户登录之后执行
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// waitUntilFinished NO 异步 YES 同步
[self.queue addOperations:@[op1, op2, op3] waitUntilFinished:NO];
// 向主队列添加操作
[[NSOperationQueue mainQueue] addOperation:op4];
NSLog(@"come here");
}
GCD与NSOperation对比
- GCD
将任务(block)添加到队列(串行/并发/主队列),并且指定任务执行的函数(同步/异步)
GCD是底层的C语言构成的API
iOS 4.0 推出的,针对多核处理器的并发技术
在队列中执行的是由 block 构成的任务,这是一个轻量级的数据结构
要停止已经加入 queue 的 block 需要写复杂的代码
需要通过 Barrier 或者同步任务设置任务之间的依赖关系
只能设置队列的优先级
高级功能:
一次性 once
延迟操作 after
调度组
- NSOperation
核心概念:把操作(异步)添加到队列(全局的并发队列)
OC 框架,更加面向对象,是对 GCD 的封装
iOS 2.0 推出的,苹果推出 GCD 之后,对 NSOperation 的底层全部重写
Operation作为一个对象,为我们提供了更多的选择
可以随时取消已经设定要准备执行的任务,已经执行的除外
可以跨队列设置操作的依赖关系
可以设置队列中每一个操作的优先级
高级功能:
最大操作并发数(GCD不好做)
继续/暂停/全部取消
跨队列设置操作的依赖关系