Swift 中的任务队列:GCD、OperationQueue 和 Swift Concurrency

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 中的任务队列:从 GCD 到 Swift Concurrency



在 iOS 和 macOS 开发中,管理代码的并行执行是一项关键任务。任务队列 (queues) 可以有效地在线程之间分配负载,而不会阻塞用户界面。在本指南中,我们将介绍三种主要方法:经典的 Grand Central Dispatch (GCD)、抽象层 OperationQueue 以及现代机制 Swift Concurrency (async/await)。



1. Grand Central Dispatch (GCD) — 并行基础



GCD 是一个集成在 Swift 中的底层 C 语言库。它管理线程池,并提供两种类型的队列:



  • 串行队列 (Serial) — 任务按添加顺序一个接一个地执行。
  • 并发队列 (Concurrent) — 任务同时启动,完成顺序不保证。


创建和使用队列的示例:



import Foundation

// 创建一个串行队列let serialQueue = DispatchQueue(label: "com.example.serial")

serialQueue.async { print("任务 1 开始") sleep(1) print("任务 1 完成")}

serialQueue.async { print("任务 2 开始") sleep(1) print("任务 2 完成")}

// 并发队列let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)

concurrentQueue.async { print("并发任务 A")}

concurrentQueue.async { print("并发任务 B")}


GCD 的关键功能:

  • DispatchQueue.main — 主队列(UI 线程)。
  • DispatchQueue.global(qos: .userInitiated) — 具有优先级 (QoS) 的全局队列。
  • dispatchGroup — 同步多个任务。
  • dispatchSemaphore — 控制对资源的访问。


2. OperationQueue — 面向对象的抽象层



OperationQueue 构建在 GCD 之上,但提供了更高级别的 API。主要优点:



  • 管理操作之间的依赖关系。
  • 取消任务 (cancel)。
  • 状态监控 (isFinished, isExecuting)。
  • 最大并发操作数。


使用 BlockOperation 的示例:



import Foundation

let operationQueue = OperationQueue()operationQueue.maxConcurrentOperationCount = 2

let operation1 = BlockOperation { print("操作 1:加载数据") sleep(2) print("操作 1 完成")}

let operation2 = BlockOperation { print("操作 2:处理") sleep(1) print("操作 2 完成")}

// 设置依赖关系:操作 2 仅在操作 1 完成后开始operation2.addDependency(operation1)

operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)

// 取消操作operation1.cancel()


何时使用 OperationQueue:

  • 具有依赖关系的复杂任务链。
  • 需要精细控制(暂停、取消)。
  • 使用 KVO (Key-Value Observing) 进行监控。


3. Swift Concurrency — 现代方法 (iOS 13+, macOS 10.15+)



从 Swift 5.5 开始,Apple 通过 async/await、Task 和 TaskGroup 引入了对异步编程的内置支持。这是一种更安全、更易读的并行处理方法。



基本示例:



import Foundation

func fetchUserData() async -> String { // 模拟网络请求 try? await Task.sleep(nanoseconds: 2 * 1_000_000_000) return "用户数据已加载"}

func processData()

推荐