You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻塞线程并从Future[A]中获取Try[A]类型结果?

阻塞获取List[Future[A]]对应List[Try[A]]的实现方案

直接用Scala标准库即可实现,不需要引入额外依赖,核心是先把每个Future的成功/失败结果提前包装成Try,避免单个Future失败导致整体聚合直接抛错,再通过Await阻塞等待所有任务完成即可。

标准实现(无额外依赖,全Scala版本兼容)

首先引入必要的依赖:

import scala.concurrent.{Await, Future, Try, Success, Failure}
import scala.concurrent.duration._

实现代码:

def collectAllFutureResult[A](
  futureList: List[Future[A]],
  timeout: Duration = 15.seconds // 根据业务实际耗时调整,禁止用无限等待
): List[Try[A]] = {
  // 把每个Future的执行结果(无论成功失败)都封装为Success/Failure,不中断整体聚合
  val tryWrappedFutures: List[Future[Try[A]]] = futureList.map { singleFuture =>
    singleFuture.transform { tryResult =>
      Success(tryResult)
    }
  }
  // 阻塞等待所有任务执行完成,返回结果顺序和入参列表顺序一致
  Await.result(Future.sequence(tryWrappedFutures), timeout)
}

避坑说明

  • 不要直接调用Await.result(Future.sequence(futureList), timeout):这种写法只要列表中任意一个Future执行失败,整个聚合结果会直接抛出对应异常,拿不到其余所有任务的执行结果,不符合返回List[Try[A]]的需求。
  • 不要遍历列表逐个调用Await.result等待单个Future:这种写法会串行等待每个任务执行,总耗时是所有任务耗时的累加,完全丢失了Future并行执行的性能优势。
  • 阻塞操作仅能用在测试代码、服务启动初始化、异步链路最外层的边缘场景,绝对不要在异步线程池的工作线程、IO线程中调用阻塞方法,否则会耗尽线程池资源引发服务故障。
  • 不要配置Duration.Inf作为超时时间,必须根据业务的SLA设置合理的超时阈值,避免线程永久阻塞。

更简洁的写法(Scala 2.13+)

如果你的项目使用Scala 2.13及以上版本,可以用更短的写法实现相同逻辑:

val resultList: List[Try[A]] = Await.result(
  Future.traverse(futureList)(_.transform(tryRes => Success(tryRes))),
  timeout
)

内容的提问来源于stack exchange,提问作者Василий Никпуп

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 23:39:35