【译】Swift并发编程三

原文地址:https://ali-akhtar.medium.com/concurrency-in-swift-operations-and-operation-queue-part-3-a108fbe27d61

并发于并行的区别

这里是Swift并发编程系列第三篇(共四篇 )。包含以下内容:

  1. Operations的状态
  2. 不同种类的Operations
  3. 如何取消Operations
  4. 什么是Operation Queue
  5. 如何使用Operation Queue管理Operations
  6. Operations的依赖管理
  7. Operations和GCD的区别

Operations

Operations是以面向对象的方式封装任务,便于异步执行。它可以配合Operation Queue使用,也可以单独使用。

Operation类是抽象基类,你必须使用其子类来完成任务。它定义了一些你在基类中必须实现的要求。另外,Foundation框架提供了两个实现,你可以直接使用。

Operations 的状态变更

一个Operation可以理解为一个状态机,也代表了其生命周期:

  1. instantiated,表示刚创建,创建完成后会转入isReady状态。
  2. 在执行完start方法后,将会转到isExecuting状态
  3. 在任务完成后,转到isFinished状态
  4. 在任务完成之前,cancel被调用,将会转到isCancelled状态

BlockOperation

这是系统提供的用于并发执行一个或多个Block的类。由于支持执行多个Block,它会存在类似group的特性,只有当BlockOperation的所有block都执行完后,这个Operation才算执行完。在BlockOperation中支持高级特性,如:依赖、KVO、通知、取消。

如下图,我们期望其异步执行。但坏消息是,它将阻塞主线程直到任务完成,因为我们在主线程调用了operation.start()

需要注意的是,若BlockOperation有多个待执行的任务,他们会并发执行,但依然会阻塞调用线程。如下图:

如果我们在其他线程调用start()方法,它也会将其阻塞:

我们可以添加Operation完成后执行的任务,他将在所有任务并发执行后执行:

NSInvocationOperation

Objective-C中的NSInvocationOperationSwift中不能使用。因为其依赖的NSInvocation及相关apiSwift中不可用。 -w922

自定义的 Operations

自定义Operations可以实现状态的完全控制。如下,我们自定义的Operation覆写了main方法,从而实现非并发Operation。它也会阻塞其调用线程。

如果你计划独立使用Operation并希望它异步执行,那还有额外的工作要做。具体的我们将在下一节专门阐述。

Operation Queues

  1. Operation Queues是基于GCD的高层抽象。
  2. 使用Operation Queues,才能发挥Operations的真正实力。你无需手动调用start方法,取而代之的是将其添加到Queue中。
  3. 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个任务,并希望他们并发执行,完成后再执行其他任务。这里我们做了如下工作:

  1. 创建一个Operation Queue
  2. 创建3个任务
  3. 继续创建了一个任务,它在之前的任务完成后才能执行
  4. blockOperations4的依赖设为之前的3个任务
  5. waitUntilFinished会阻塞当前线程,直到所有任务完成。这里我们传入false

相比 GCD,Operation Queues的优点

  1. 相比GCD,可以很方便的设置任务的依赖
  2. 支持使用KVO监听任务的执行状态
  3. 任务支持暂停,取消。而使用GCD提交的任务,无法取消
  4. 更方便的控制并发数量