使用Grand Central Dispatch进行并行计算和编程

我们将使用原生的Grand Central Dispatch( GCD )框架研究iOS上Swift的并发编程。 如果您不熟悉并发编程,建议您先看一下Wikipedia。 让我们开始研究此API背后的哲学和良好实践。

GCD (Grand Central Dispatch)是一个框架,提供低级API来处理iOS,macOS,tvOS和watchOS平台上的并发编程。 苹果公司提供竞争管理的所有更高级别的框架(例如NSOperation )都基于GCD 。 这些API允许您将流程的工作划分为各个任务,然后使用队列帮助协调并行或顺序执行这些任务。 它使我们能够从线程,处理器或核心的概念中抽象出来,并同时利用其自己的线程池来优化资源管理。

GCD所基于的基本概念是FIFO(先进先出)。 我们要执行的任务将首先插入到这些队列中,然后GCD将单独检索它们,以将它们分派到正确的线程/处理器/心脏。 我们可以区分两种文件:

  • 并发文件:并行执行多个任务
  • 顺序或串行 文件:连续执行一对一的任务

这是现有文件的3类:

  • Main queue :等同于主要处理应用程序UI的主线程。 所有UI调用都必须在此队列上完成。
  • Global queue :系统为我们提供3个具有不同优先级(高,默认和低)的全局尾部。 这3个文件是Concurrent类型的。
  • Custom queue :可以手动创建并具有所需类型(串行或并发)的队列。

让我们从创建3个队列类别之一开始:

为了创建自定义队列 ,我们首先定义一个标识符(建议使用反向DNS格式)。

现在我们知道了如何创建文件,如何使用它们? 非常简单,这要感谢“调度员”! 这是一个小例子:

让我们分解所有这些。 我们开始创建低优先级队列。 然后,我们在先前恢复的低优先级队列上异步“分发”代码块。 该代码块异步获取数据以将其存储在data变量中。 最后,我们使用恢复的数据更新主线程中的view 。 在主线程中执行最后一步非常重要,因为UIKit不是线程安全的,并且如果您在另一个线程中更新组件,则应用程序可能崩溃或具有未定义的行为。

控制台将在此处显示:

 之前 

内部异步块
在主队列块内
完蛋了!

使用GCD您可以管理所有有关并发编程的问题。 在本节中,我们将进一步介绍不同的使用情况。

让我们讨论一个用例,其中您要执行多个任务,并且想要等到所有这些任务完成之后再执行其他操作。 为此,必须使用DispatchGroup

为了等待所有任务完成,我们创建了一个group并在循环中定义了任务何时在组中开始,尤其是定义了任务何时完成。 我们必须将其想象为一个计数器,每个enter该计数器的计数器都加1, leave每个计数器的计数器都减1。最后,我们定义一个notif块,该块监听该group的计数器并执行给定的块他变为0时进入queue 。此处的控制台输出为:(完成的作业顺序可能有所不同)

  开始工作0 
开始工作1
开始工作2
开始工作3
开始工作4
开始工作5
开始工作6
开始工作7
开始工作8
开始工作9
完成工作3
完成工作2
完成的工作1
完成工作4
已完成工作0
完成工作9
完成工作5
完成工作6
完成工作8
完成工作7
所有工作都完成了!

第二种非常有用的情况可能是希望在一定时间后执行代码。 如果您遇到这种情况,请立即考虑GCD及其asyncAfter方法:

GCD是一个非常强大的框架,可让您真正摆脱并发编程中固有的低级约束。 但是,要充分利用此潜力,您需要注意共享内存问题和同步。 在这里深入了解。