如何阻塞线程并从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,提问作者Василий Никпуп
相关产品推荐
相关产品推荐

