Swift 4中线程1等待线程2执行的多线程同步问题咨询
Swift 4多线程同步:实现线程等待逻辑
看起来你已经选对了方向——用DispatchGroup来处理多线程同步问题,这是Apple官方推荐的解决这类"等待一组任务完成"场景的方案。我帮你补全代码并解释核心逻辑,完美解决线程等待的需求。
核心思路
DispatchGroup的工作原理很简单:
- 每启动一个需要等待的异步任务前,调用
enter()(相当于告诉Group"我要开始一个任务了") - 任务完成后,调用
leave()(告诉Group"我的任务做完了") - 当所有
enter()的任务都调用了leave(),Group就会触发notify闭包,或者解除wait()的阻塞
根据你的需求,分两种常见场景实现:
场景1:两个任务并行执行,都完成后再执行后续逻辑
如果你的需求是doSomethingFromJSON1和doSomethingFromJSON2可以并行跑,但必须等它们都完成后,再执行downloadImage、lastThread等后续任务,代码如下:
func doSomethingFromJSON1() { print("1") } func doSomethingFromJSON2() { print("2") } func downloadImage() { print("3") } func waitingForNext() { print("4 - waiting") } func lastThread(){ print("Last THREAD") } func finishFunction(){ print("Finish") } func doItAll() { let dispatchGroup = DispatchGroup() // 任务1:doSomethingFromJSON1 dispatchGroup.enter() DispatchQueue.global().async { // 用defer保证即使任务抛出异常,leave也会被调用 defer { dispatchGroup.leave() } self.doSomethingFromJSON1() } // 任务2:补全你未完成的doSomethingFromJSON2逻辑 dispatchGroup.enter() DispatchQueue.global().async { defer { dispatchGroup.leave() } self.doSomethingFromJSON2() } // 非阻塞式等待:所有任务完成后,在指定队列执行后续逻辑 dispatchGroup.notify(queue: DispatchQueue.global()) { // 前两个任务都完成了,执行downloadImage self.downloadImage() // 如果waitingForNext也需要异步执行并等待,继续用Group let innerGroup = DispatchGroup() innerGroup.enter() DispatchQueue.global().async { defer { innerGroup.leave() } self.waitingForNext() } // 最后回到主线程执行收尾(比如更新UI) innerGroup.notify(queue: DispatchQueue.main) { self.lastThread() self.finishFunction() } } }
场景2:线程1(doSomethingFromJSON1)必须等待线程2(doSomethingFromJSON2)完成后才启动
如果你的需求是明确的"线程1要等线程2做完才能开始",可以简化逻辑,把线程1的任务放在线程2完成后的通知闭包里:
func doItAll() { let dispatchGroup = DispatchGroup() // 先启动线程2的任务 dispatchGroup.enter() DispatchQueue.global().async { defer { dispatchGroup.leave() } self.doSomethingFromJSON2() // 线程2执行 } // 等待线程2完成后,启动线程1 dispatchGroup.notify(queue: DispatchQueue.global()) { self.doSomethingFromJSON1() // 线程1现在才开始执行 // 线程1完成后,继续后续任务 self.downloadImage() self.waitingForNext() // 回到主线程收尾 DispatchQueue.main.async { self.lastThread() self.finishFunction() } } }
关键注意事项
enter()和leave()必须成对出现:如果enter()比leave()多,Group会永远等待;如果leave()多,会导致崩溃。用defer包裹leave()是最安全的方式,能避免异常或提前返回导致的遗漏。- 避免在主线程调用
wait():wait()会阻塞当前线程,如果在主线程调用,会导致UI冻结,用户体验极差。优先用notify()这种非阻塞方式。 - 队列选择:异步任务尽量放在全局后台队列(
DispatchQueue.global()),涉及UI更新的收尾逻辑一定要切回主线程(DispatchQueue.main)。
内容的提问来源于stack exchange,提问作者Łukasz Betta
相关产品推荐
相关产品推荐

