原文地址:https://ali-akhtar.medium.com/concurrency-in-swift-operations-and-operation-queue-part-3-a108fbe27d61
这里是Swift并发编程系列
第三篇(共四篇 一、二)。包含以下内容:
- Operations的状态
- 不同种类的Operations
- 如何取消Operations
- 什么是Operation Queue
- 如何使用Operation Queue管理Operations
- Operations的依赖管理
- Operations和GCD的区别
Operations
Operations
是以面向对象的方式封装任务,便于异步执行。它可以配合Operation Queue
使用,也可以单独使用。
Operation
类是抽象基类,你必须使用其子类来完成任务。它定义了一些你在基类中必须实现的要求。另外,Foundation
框架提供了两个实现,你可以直接使用。
Operations 的状态变更
一个Operation
可以理解为一个状态机
,也代表了其生命周期:
instantiated
,表示刚创建,创建完成后会转入isReady
状态。- 在执行完
start
方法后,将会转到isExecuting
状态 - 在任务完成后,转到
isFinished
状态 - 在任务完成之前,
cancel
被调用,将会转到isCancelled
状态
BlockOperation
这是系统提供的用于并发执行一个或多个Block
的类。由于支持执行多个Block
,它会存在类似group
的特性,只有当BlockOperation
的所有block
都执行完后,这个Operation
才算执行完。在BlockOperation
中支持高级特性,如:依赖、KVO、通知、取消。
如下图,我们期望其异步执行。但坏消息是,它将阻塞主线程直到任务完成,因为我们在主线程调用了operation.start()
需要注意的是,若BlockOperation
有多个待执行的任务,他们会并发执行,但依然会阻塞调用线程。如下图:
如果我们在其他线程调用start()
方法,它也会将其阻塞:
我们可以添加Operation
完成后执行的任务,他将在所有任务并发执行后执行:
NSInvocationOperation
在Objective-C
中的NSInvocationOperation
在Swift
中不能使用。因为其依赖的NSInvocation
及相关api
在Swift
中不可用。
自定义的 Operations
自定义Operations
可以实现状态的完全控制。如下,我们自定义的Operation
覆写了main
方法,从而实现非并发
的Operation
。它也会阻塞其调用线程。
如果你计划独立使用Operation
并希望它异步执行,那还有额外的工作要做。具体的我们将在下一节专门阐述。
Operation Queues
Operation Queues
是基于GCD
的高层抽象。- 使用
Operation Queues
,才能发挥Operations
的真正实力。你无需手动调用start
方法,取而代之的是将其添加到Queue
中。 Operation Queues
是以面向对象的方式管理那些需要异步执行的任务。
使用Operation Queues
如下图,我们以Block
的方式创建了两个Operation
,并将他们添加到Queue
中。之后这两个Operation
均在后台线程开启并执行。当我们把Operation
添加到Queue
中,它就会尽快执行。
如果你想顺序的执行多个任务,只需将maxConcurrentOperationCount
设置为1
。如下:
maxConcurrentOperationCount
限制了Queue
中的Operation
并发数量,默认值为-1
,这意味着由系统决定最大并发数量。
依赖管理
如下图,我们可以通过在两个任务之间添加依赖来形成顺序执行的效果。
使用Operations Queue实现Dispatch Group
在之前的部分,我们使用GCD dispatch group
实现了等待多个任务完成后继续之前的任务的效果。这里我们也可以使用Operation Queue
来实现。
如上图,我们有3个任务,并希望他们并发执行,完成后再执行其他任务。这里我们做了如下工作:
- 创建一个
Operation Queue
- 创建3个任务
- 继续创建了一个任务,它在之前的任务完成后才能执行
- 将
blockOperations4
的依赖设为之前的3个任务 waitUntilFinished
会阻塞当前线程,直到所有任务完成。这里我们传入false
。
相比 GCD,Operation Queues的优点
- 相比GCD,可以很方便的设置任务的依赖
- 支持使用KVO监听任务的执行状态
- 任务支持暂停,取消。而使用GCD提交的任务,无法取消
- 更方便的控制并发数量