Java中Callable不能直接返回ListenableFuture,需通过ListeningExecutorService提交Callable获取;可用MoreExecutors.listeningDecorator包装ExecutorService,再用Futures.addCallback注册回调,注意选择合适的回调执行器。

Java 中 Callable 本身返回的是普通 Future(来自 java.util.concurrent),而 Guava 的 ListenableFuture 是其增强版,支持注册回调。你不能直接让 Callable 返回 ListenableFuture,但可以通过 ListeningExecutorService 将普通 Callable 提交后获得 ListenableFuture。
用 ListeningExecutorService 包装线程池
Guava 提供了 MoreExecutors.listeningDecorator 方法,把标准的 ExecutorService 转成支持监听的版本:
- 先创建一个普通线程池(如
Executors.newCachedThreadPool()) - 用
MoreExecutors.listeningDecorator包装它,得到ListeningExecutorService - 调用它的
submit(Callable<T>)方法,返回的就是ListenableFuture<T>
示例代码:
ExecutorService delegate = Executors.newCachedThreadPool();
ListeningExecutorService service = MoreExecutors.listeningDecorator(delegate);
Callable<String> task = () -> {
Thread.sleep(1000);
return "Done";
};
ListenableFuture<String> future = service.submit(task);
// 添加成功回调
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("Success: " + result);
}
@Override
public void onFailure(Throwable t) {
System.err.println("Failed: " + t.getMessage());
}
}, MoreExecutors.directExecutor()); // 指定回调执行器
注意回调执行器的选择
Futures.addCallback 第三个参数是回调执行的线程上下文:
立即学习“Java免费学习笔记(深入)”;
-
MoreExecutors.directExecutor():在Future完成的同一线程中立即执行回调(适合轻量、无阻塞逻辑) - 传入自定义
Executor:更安全,避免阻塞任务线程,推荐用于 I/O 或耗时操作
不要试图在 Callable 内部创建 ListenableFuture
Callable.call() 方法签名强制返回 T,不是 Future。所以不能在 Callable 里 new 一个 ListenableFuture 并返回——这会编译失败。正确做法始终是:由外部的 ListeningExecutorService 提交 Callable,再对返回的 ListenableFuture 做监听。
替代方案:用 SettableFuture 手动控制(进阶)
如果需要完全自定义异步逻辑(比如封装第三方异步 API),可不用 Callable,改用 SettableFuture:
- 创建
SettableFuture.create() - 在任意线程中调用
set(result)或setException(e) - 它本身就是
ListenableFuture,可直接添加回调
这种模式更适合事件驱动或响应式场景,而非传统线程池任务提交。


















