IOS 多线程:NSOperation & NSOperationQueue
https://www.jianshu.com/p/d973cd1acc32
IOS 线程
主线程又称为 UI 线程。主线程一般用来刷新 UI 界面,处理 UI 事件(比如:点击、滚动、拖拽等事件)。不要将耗时的操作放在主线程
1. 创建多线程的技术
- pthread:c语言的,跨平台,适用于 Unix/Linux/Windows等系统。线程生命周期需要程序员管理。使用难度大
- NSThread:OC语言的,面向对象,直接操作线程对象,程序猿管理线程生命周期
- GCD:充分利用设备的多核,C语言,自动管理线程生命周期。
- NSOperation:OC 语言,底层是 GCD,面对对象,自动管理线程生命周期。
二、GCD 使用
Grand Central Dispatch ,纯 C 语言。GCD 会自动利用更多的 CPU 内核,GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
GCD 队列分为并发队列(dispatch_async)、串行队列(dispatch_sync)
1. 主队列
异步任务:不开线程,有序执行,主队列特点:先执行完主线程上的代码,才会执行主队列中的任务。主队列又叫做全局串行队列
同步执行:如果在主线程上执行,则会死锁
1 | - (void)demo5 { |
2. 全局队列
本质就是并发队列。区别
- 并发队列有名称,可以跟踪错误,全局队列没有
- 并发队列是 create 创建出来的,在 MRC 中就需要 release。全局队列不需要 release
- 一般使用全局队列
1 | dispatch_get_global_queue(intptr_t identifier, uintptr_t flags) |
3. 同步任务
很多事情都有先后顺序
4. 队列之间对比
全局并行队列 | 手动创建串行队列 | 主队列 | |
---|---|---|---|
同步(sync) | 没有开启新线程 串行执行任务 |
没有开启新线程 串行执行任务 |
会死锁 |
异步(async) | 有开启新线程 并行执行任务 |
有开启新线程 串行执行任务 |
没有开启新线程 串行执行任务 |
5. Barrier
主要用于在多个异步操作完成之后,统一对非线程安全的对象进行更新。
等待队列中所有任务执行完成,才会执行 barrier 中的代码
1 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ |
6. 延迟执行和一次性执行
1 | dispatch_after |
三、NSOperation 使用
NSOperation 是一个抽象类,NSOperation 的子类:NSInvocationOperation、NSBlockOperation、自定义 operation
NSOperation 和 NSOpertionQueue 实现多线程的具体步骤:
- 先将需要执行的操作封装到一个 NSOperation 对象中
- 然后将 NSOperation 对象添加到 NSOperationQueue 中
- 系统会自动将 NSOperationQueue 中的 NSOperation 取出来,将取出来的 NSOperation 封装的操作放到一条新线程中执行
1.NSInvocationOperation 使用
start 方法的更新操作的状态,然后调用 main 方法。不会开启新线程,是在主线程上调用的
也可以加入到队列中执行,是在子线程上调用
1
2
3
4
5
6
7
8
9- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSInvocationOperation* op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(demo) object:nil];
// [op start];
NSOperationQueue* queue = [[NSOperationQueue alloc]init];
[queue addOperation:op];
}
- (void)demo {
NSLog(@"cur thread: %@", [NSThread currentThread]);
}
2. NSBlockOperation 使用
默认 并发队列、异步执行
1 | - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { |
3. 线程间通信
1 | [self.queue addOperationWithBlock:^{ |
3. Barrier 阻塞
主要用于在多个异步操作完成之后,统一对非线程安全的对象进行更新。适合于大规模的 IO 操作。
当访问数据库或文件的时候,更新数据的时候不能和其他更新或读取的操作在同一时间执行,使用 dispatch_barrier_async 解决。
4. 其他
1 | // 设置最大并发数 |
三、NSOperation 和 GCD 的对比
GCD:
- GCD 是IOS 4.0 推出的,主要针对多核 CPU 做了优化,是 C 语言的技术
- GCD 是将任务(block)添加到队列(串行、并行、全局、主队列),并且以同步、异步的方式执行任务的函数
- GCD 提供了一些 NSOperation 不具备的功能
- 一次性执行
- 延迟执行
- 调度组
NSOperation
- NSOperation 是 IOS2.0 推出的,IOS4 之后重写了 NSOperation
- NSOperation 将操作(异步的任务)添加到队列(并发队列),就会执行指定操作的函数
- NSOperation 里提供的方便的操作
- 最大并发数
- 队列的暂停、继续
- 取消所有操作
- 取消操作之间的依赖关系(GCD可以用同步实现)