NSOperation
1. 简介
OC语言基于CGD的面向对象装.提供了一些GCD不好实现的功能,苹果推荐使用;同样比比关系线程和生命周期.
NSOperation是一个抽象类,不能直接使用(方法没有实现),是用来约束子类都具有共同的属性和方法.
主要使用NSOperation的子类:
- NSInvocationOperation
- NSBlockOperation
- 自定义Operation
2. 简单使用
步骤:
- 将需要执行的操作封装到NSOperation对象对象中.
- 将对象添加到NSOperationQueue队列中;(不同类型对象加到同一个队列中)
之后系统会自动将NSOperation取出,放到一条新线程中;
2.1 NSInvocationOperation 的使用
- 调用NSInvocationOperation 的 initWithTarget: selector: object:方法来创建此对象;
- 调用对象方法 start来调用;
- 注意:默认情况下,调用start方法后并不会开启一条新线程去执行操作,只有将NSOperation操作放到一个NSOperationqueue中,才会异步执行操作;
例:
//1.创建操作
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];
//start方法更新操作的状态 调用main方法
//[op start]; //不开启新线程,一般是不会这么操作的;
//2.创建队列
NSOperationQueue *queue = [NSOperation alloc] init];
//3.把操作添加到队列
[queue addOperation:op]; //这样才能异步执行;
2.2 NSBlockOperation 的使用—常用!
使用步骤同上,只是操作直接写在block块内;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
[queue addOperation:op];
//可以直接添加block块, 省去第二步创建操作对象;
[queue addOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
// 简易模式.
[NSOperationQueue new] addOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
线程通信如果子线程中需要更新UI控件的,调用 转到主线程执行操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^ { }];即可
线程同步监听操作完成,
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2];
NSLog(@"hello %@",[NSThread currentThread]);
}];
//hello打印操作完成之后才会执行end打印
[op setCompletionBlock:^{
NSLog(@"end %@",[NSThread currentThread]);
}];
[self.queue addOperation:op];
2.3 自定义Operation
3. NSOperation的高级功能
介绍之前先简单对比下GCD的区别:
- GCD是将任务(block)添加到队列(串行/并行/全局/主队列),并且以同步/异步的方式执行任务的函数
- 附加功能:
- 一次性执行
- 延迟执行
- 调度组
- NSOperation将操作(异步的任务)添加到队列(并发队列),就会执行指定操作的函数
- 附加功能:
- 最大并发数
- 队列的暂停与继续
- 取消队列操作
- 可以直接指定操作件的依赖关系
3.1 最大并发数
设置队列 queue 同时执行的任务数,可以间接的控制子线程的创建数量;
queue点语法或值setMaxConcurrentOperationCount: 来设置
queue.OperationCount获取队列中操作数
3.2 队列暂停与取消操作
取消和暂停操作不会对正在执行的操作有影响;
暂停: 点语法和set方法设置suspended.
self.queue.suspended = YES; //暂停 要继续赋值NO即可;
取消:
//取消所有操作.清空队列.
[self.queue cancelAllOperations];
//取消当个操作
[operation cancel];//不需要写额外代码 比GCD和NSThread要省心
另外:
同NSThread一样有操作优先级设置,iOS8之后叫服务质量qualityOfService;操作优先级高,只是表示操作被优先执行的几率高,并不是说优先级高的操作先执行,优先级低的操作后执行;
点语法和set方法设置qualityOfService;值是枚举类型,依次从高到低;
- 用户交互: NSQualityOfServiceUserInteractive = 0x21
- 用户主动发起: NSQualityOfServiceUserInitiated = 0x19
- 实用工具: NSQualityOfServiceUtility = 0x11
- 后台: NSQualityOfServiceBackground = 0x09
- 默认: NSQualityOfServiceDefault = -1
3.3 解决线程同步,操作依赖
NSOperation直接可以直接设置依赖关系,来保证线程同步;(可以再不同的队列中操作直接创建依赖关系)
[operationB addDependency:operationA]; // 操作B依赖于操作A
注意: 不要循环依赖–死锁;