如何让返回Future[Unit]的方法中外层Future等待嵌套Future完成?
如何让Scala中外层Future等待嵌套Future完成后再结束?
先贴出你的现有代码和当前输出,方便大家理解问题:
现有taskA方法实现
def taskA(): Future[Unit] = Future { Future { print("Starting nested future") Thread.sleep(3000) print("Finished nested future") } print("starting outer future") Thread.sleep(1000) print("finished outer future") }
执行代码
print("Starting program") val futureA = taskA() futureA onComplete{ case Success(_) => print("future suceeded") case Failure(_) => print("not able to execute future") } Await.result(futureA, Duration.Inf)
当前控制台输出
15:18:52.357 [main] Starting program 15:18:52.563 [scala-execution-context-global-13] Starting nested future 15:18:52.564 [scala-execution-context-global-12] starting outer future 15:18:53.564 [scala-execution-context-global-12] finished outer future 15:18:53.566 [scala-execution-context-global-12] future suceeded Process finished with exit code 0
当然可以实现!我来给你拆解问题和解决方案:
你当前的代码问题在于:外层Future只是创建了嵌套Future,但完全没等待它完成——嵌套Future被丢到线程池独立运行后,外层就自顾自执行后续代码然后结束了,这就是为什么外层先触发成功回调的原因。要让外层等嵌套完成,我们需要把两个Future的执行逻辑绑定起来,而非让它们各自独立运行。
推荐方案:用for推导式实现顺序执行(最直观)
这种写法能清晰表达“先完成嵌套Future的逻辑,再执行外层逻辑”的需求,而且是非阻塞的,不会浪费线程资源:
import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global def taskA(): Future[Unit] = { for { // 第一步:执行嵌套Future,等待它完成 _ <- Future { print("Starting nested future\n") Thread.sleep(3000) print("Finished nested future\n") } // 第二步:嵌套完成后,再执行外层逻辑 _ <- Future { print("starting outer future\n") Thread.sleep(1000) print("finished outer future\n") } } yield () }
等价写法:用flatMap链式调用
如果你熟悉函数式编程风格,flatMap和上面的for推导是完全等价的,只是写法更偏链式调用:
def taskA(): Future[Unit] = { val nestedFuture = Future { print("Starting nested future\n") Thread.sleep(3000) print("Finished nested future\n") } // 等待嵌套Future完成后,再启动外层的Future nestedFuture.flatMap { _ => Future { print("starting outer future\n") Thread.sleep(1000) print("finished outer future\n") } } }
不推荐的临时方案:阻塞等待
如果你只是想快速验证效果,也可以在外层Future里用Await.result强制等待嵌套完成,但这种方式会阻塞线程,生产环境或高并发场景下不建议使用:
import scala.concurrent.Await import scala.concurrent.duration.Duration def taskA(): Future[Unit] = Future { val nested = Future { print("Starting nested future\n") Thread.sleep(3000) print("Finished nested future\n") } // 强制阻塞当前线程,直到嵌套Future完成 Await.result(nested, Duration.Inf) // 嵌套完成后再执行外层逻辑 print("starting outer future\n") Thread.sleep(1000) print("finished outer future\n") }
修改后的输出效果
用推荐方案执行后,输出顺序会完全符合预期:
Starting program Starting nested future Finished nested future starting outer future finished outer future future suceeded Process finished with exit code 0
外层Future会严格等到嵌套Future完成后,才执行自身逻辑并触发成功回调。
内容的提问来源于stack exchange,提问作者Berni
相关产品推荐
相关产品推荐

