Swift 中的并发与多线程入门
现代 iOS 和 macOS 应用必须快速且响应灵敏。用户不应该等待图片加载或复杂计算完成。为此,Swift 提供了并发和多线程机制。在本文中,我们将从经典的 Grand Central Dispatch (GCD) 到现代 Swift Concurrency 中的 async/await,解析关键概念。
并发 (concurrency) 是指程序同时执行多个任务并在它们之间切换的能力。多线程 (multithreading) 是并发的一种实现方式,其中任务在操作系统的不同线程中执行。Swift 为处理这些概念提供了强大且安全的工具。
1. Grand Central Dispatch (GCD) — 多线程的基础
Grand Central Dispatch (GCD) 是 Apple 用于管理代码并行执行的低级库。它基于队列 (dispatch queues) 工作。
GCD 中的队列类型
- Serial Queue (串行队列) — 任务按添加顺序一个接一个执行。
- Concurrent Queue (并发队列) — 任务可以在不同线程上同时执行。
- Main Queue (主队列) — 在主线程上执行任务,用于更新 UI。
- Global Queues (全局队列) — 具有不同优先级 (QoS) 的系统并发队列。
示例:在后台执行任务并更新 UI
import UIKit
class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView!
func loadImage(from url: URL) { // 切换到后台队列 DispatchQueue.global(qos: .background).async { [weak self] in guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return } // 返回主线程更新 UI DispatchQueue.main.async { self?.imageView.image = image } } }}在这个示例中,我们在后台线程下载图片以避免阻塞界面,然后在主线程更新 UI。
使用 DispatchGroup 同步任务
DispatchGroup 允许跟踪一组异步任务的执行,并在它们全部完成后执行操作。
let group = DispatchGroup()
group.enter()fetchData1 { result in print("数据 1 已获取") group.leave()}
group.enter()fetchData2 { result in print("数据 2 已获取") group.leave()}
group.notify(queue: .main) { print("所有数据已加载,更新 UI")}2. OperationQueue — 面向对象的方法
OperationQueue 是建立在 GCD 之上的更高级抽象。它使用 Operation 对象,这些对象代表一个工作单元。
OperationQueue 的优势
- 能够取消任务 (cancel)。
- 在操作之间设置依赖关系 (addDependency)。
- 监控操作状态 (isFinished, isExecuting, isCancelled)。
- 配置最大并发操作数。
示例:加载多个图片
import UIKit
class ImageLoader { private let queue = OperationQueue() func loadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) { var images: [UIImage] = [] let completionOperation = BlockOperation { DispatchQueue.main.async { completion(images) } } for url in urls { let o