ListenableFuture 通过继承 Future 并新增监听能力实现异步升级,必须由 ListeningExecutorService 创建;推荐用 Futures.addCallback 注册回调并指定执行器,支持 transform/ catching 链式处理;新项目应优先选用 CompletableFuture。

Guava 的 ListenableFuture 并不是对原生 Future 的“包装扩展”,而是通过接口继承(extends Future)+ 新增能力的方式,在语义和使用模式上实现质的升级:它让异步任务真正可“监听”,不再依赖轮询或阻塞 get()。
必须用 ListeningExecutorService 创建
原生 Future 由 ExecutorService.submit() 返回,而 ListenableFuture 只能由 ListeningExecutorService 创建——这是硬性前提,不能靠转换或装饰已有 Future。
- 用
MoreExecutors.listeningDecorator(executor)包装你已有的线程池(如ThreadPoolExecutor) - 调用该装饰器的
submit()或invokeAll()方法,返回值才是真正的ListenableFuture - 直接 new
ListenableFutureTask也可行,但需手动管理生命周期,不推荐在业务中使用
注册回调要明确执行线程
监听器的执行上下文不由任务线程决定,而是由你传入的 Executor 控制——这点极易出错,尤其在 UI 或 Web 主线程场景中。
- 用
Futures.addCallback(future, callback, executor)是最清晰的方式:callback 实现onSuccess/onFailure,executor 指定回调在哪跑 - 若想切回主线程(如 Android 或 Swing),传
ContextCompat.getMainExecutor(context)或SwingUtilities.invokeLater封装的 executor - 避免滥用
MoreExecutors.directExecutor():它把回调压进当前线程(可能是 IO 线程或 Tomcat 工作线程),一旦回调耗时,会阻塞整个线程池
构建异步流水线:transform 和 catching
比起单纯监听完成事件,ListenableFuture 更强的是支持链式异步处理,类似 CompletableFuture 的 thenApply 和 exceptionally。
-
Futures.transform(input, function, executor):对成功结果做同步转换,返回新ListenableFuture;若需异步转换(比如再发一次 HTTP 请求),用AsyncFunction版本 -
Futures.catching(input, exceptionClass, fallback, executor):只捕获指定类型异常(如IOException),返回默认值或重试 future;其他异常仍向上抛 - 每层
transform或catching都生成新 future,逻辑清晰,但嵌套过深可能增加调度开销(一般可忽略)
注意兼容性与演进趋势
ListenableFuture 是 JDK 8 之前最成熟的回调方案,但它正逐步被官方收编和替代。
- 如果你项目仍在用 JDK 7、Spring 4.x 或 Dubbo 2.6,
ListenableFuture是稳妥选择——这些老框架不认CompletableFuture作为 RPC 返回类型 - Guava 28+ 已将
ListenableFuture标记为@Beta,新项目应优先选用CompletableFuture,它原生支持函数式链式调用、更丰富的组合操作,且无需额外依赖 - 迁移成本不高:多数
Futures.addCallback场景可直接转为whenComplete或handle,transform对应thenApply,catching对应exceptionally或handle











