NSOperation是iOS中实现多线程的一个重要模块,在这里整理一些容易忽略或者模糊的点,不会有太多基础的知识。
先大致介绍一些基本知识。
核心的两个类 NSOperation 和 NSOperationQueue
概述
NSOperation可以理解为待执行的任务。
NSOperationQueue是保存任务的队列。
NSOperation
使用NSOperation一共有三种方式
- NSBlockOperation(block形式)
- NSInvocationOperation(selector形式)
- 继承NSOperation
第一种就是用block的方式实现需要执行的任务;第二种就是使用selector的方式;第三种,由于NSOperation本身是一个基类,内部主要实现operation状态、控制等,没有提供任务接口,所以需要自己继承。
NSOperationQueue
使用NSOperationQueue一共有两种方式
- 主队列,[NSOperationQueue mainQueue]
- 其他队列,[[NSOperationQueue alloc] init]
第一种队列加入的任务默认是在主线程中执行,由于默认的最大并发数 maxConcurrentOperationCount = 1,所以在主队列中执行的任务只能是串行执行;第二种自行init的队列默认并发数是-1,所以在该种队列中的任务会并发执行。
下面到了重点了。(由于方便比较结果,所以下面都统一用 NSBlockOperation 来演示)
NSBlockOperation 中有两个方法来增加任务,一个是默认的构造方法 NSBlockOperation blockOperationWithBlock
;另一个是用来增加任务的 addExecutionBlock
。那么问题来了,通过addExecutionBlock
增加的任务到底是按照什么方式执行的呢?在不同的队列(主队列、其他队列)中会不会有不同呢?多个队列之间的执行又是什么样的呢?
下面就通过几个例子来说明这些问题
1. addExecutionBlock的任务是串行还是并行执行的呢?
|
|
输出有多种情况
可以看出,虽然add在了主队列中,同一个operation中的不同任务(这里可以叫做execution)不一定是串行的。通过addExecutionBlock
的execution有可能是在其他线程中执行,也可能是在主线程中执行,但是一定会有一个execution在主线程中执行。
2. mainQueue中的多个operation是怎么执行的?
|
|
可以看出,主队列中add的不同operation是串行执行的,但是每个operation内部多个不同execution仍然是并行的。
所以通过前两个例子可以充分了解 maxConcurrentOperationCount = 1 时所谓的串行是指队列中多个operation之间是串行的,但每个operation之间不同的execution仍然是并行的。
由于其他队列都是并发的,情况比较容易理解,所以就不再单独讲其他队列的情况
3. 多个队列的执行情况
其实多个队列的执行情况也容易理解,多个队列之间都是不相干的(没有dependency的情况下),所以就是单纯的并发。
|
|
可以看到,所有任务之间都是单纯的并发,不会存在不同类型队列之间的依赖关系(就是不会有一定先执行主队列,再执行其他队列的情况。但优先级可能会有不同,这个不确定,多次打log发现大部分情况第一个输出的还是主队列的一个任务)