一、Future是什么
- future是"异步计算的凭证",启动线程池异步计算后,如果想拿到结果该怎么获取?使用异步线程池返回的Future
- 线程池的submit方法的返回值类型就是Future
- 怎么获取返回的结果?调用Future的get()/get(long timeout, TimeUnit unit)
@Testpublic void testSXFCache() throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(10);Future<Integer> future = executorService.submit(() -> {try {Thread.sleep(2000);return 20;} catch (InterruptedException e) {throw new RuntimeException(e);}});Integer integer = future.get();executorService.shutdown();log.info("结果为:{}", integer);}
二、Future的作用
不同的Future实现类有不同的额外作用,Future类是最顶层的抽象类,它的核心价值是:
- 提交任务后,立刻拿到"提货单":线程池/异步框架执行耗时任务时,不会阻塞调用线程,而是返回一个"提货单"Future,可以让调用线程执行完其他操作后,再获取异步任务的结果
- 提供 结果、控制、状态三大能力:
| 结果 | get() / get(timeout) 获取计算结果(可阻塞可超时) |
|---|
| 状态 | isDone() / isCancelled() 查询任务是否完成/被取消 |
| 控制 | cancel(mayInterruptIfRunning) 尝试取消任务 |
三、Future的常用API
| 方法 | 说明 |
|---|
V get() | 阻塞直到任务完成并返回结果 |
V get(long timeout, TimeUnit unit) | 带超时的阻塞 |
boolean cancel(boolean mayInterruptIfRunning) | 尝试取消任务 |
boolean isCancelled() | 任务是否已取消 |
boolean isDone() | 任务是否已结束(含正常/异常/取消) |
四、底层AQS
这个后面还要继续深入学习
五、Future的回调/注册监听器
1、JDK原生Future
2、CompletableFuture
- 链式回调:thenApply、thenApplyAsync等等这些方法都会返回新的 CompletableFuture,可无限链。
- 这个后面还需要再学习
3、ListenableFuture
- 使用addListener 方法回调
- addListener方法可以通过异步线程池创建新的线程执行回调方法
- 核心方法:
| 方法 | 是否异步 | 默认线程池 | 示例 |
|---|
addListener(Runnable, Executor) | 由 Executor 决定 | 必须传 | 同步用 directExecutor(),异步传线程池 |
Futures.addCallback(f, callback, executor) | 同上 | 必须传 | 等价写法,更友好 |
- 触发条件:Future 被标记为“已完成”(isDone() 瞬间变成 true),无论结果是成功、失败、取消或异常,只要状态变成已完成,就会触发回调。
六、Future与线程池的关系
- Future是获取结果的类,是"提货凭证";
- 线程池是实现异步的方式,线程池可以实现异步的效果;线程池可以开启新的线程执行,不阻断调用线程
七、几种Future实现类
CompletableFuture (JDK 8+ 自带)
- 不需要通过创建异步线程池的得到CompletableFuture,调用CompletableFuture的supplyAsync无参方法时,它会把任务提交到默认的ForkJoinPool.commonPool()(一个JVM全局共享、大小 = CPU 核心数-1的线程池,无需手动创建 )
- 也可以显示指定线程池
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> heavyTask());
ExecutorService myPool = Executors.newCachedThreadPool();
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> heavyTask(), myPool);
ListenableFuture
- Google Guava 提供
- Futures.immediateFuture方法:
| 零延迟 | 返回瞬间 isDone() = true,get() 立刻拿到原值;无后台线程。 |
| 零阻塞 | 调用 get() 不会睡线程;主线程继续跑。 |
| 零异常 | 除非你把 null 当异常,否则永不抛 ExecutionException。 |
| 零资源 | 内部只是一个 ImmediateFuture 单例,不创建 Thread、不占用线程池。 |
| 特点 | 说明 |
|---|
| 零延迟 | 调用该方法后立刻拿到原值,无后台线程;立即返回isDone() = true |
| 零阻塞 | 这个方法是同步方法,同步返回,但调用get方法不会阻塞主线程,主线程继续跑 |
| 零资源 | 不创建Thread、不占用线程池 |
- 个人理解这个方法的目的:返回一个future类型对象,传入一个value,不需要异步线程执行任何操作,调用get方法时,返回传入的value,仅此而已;目的是保持代码统一,调用方法时都能使用Future对象接收,都可以调用get方法、isDone方法。
SettableFuture
- Google Guava 提供
- SettableFuture类似空白支票,
- “可手动完成”**的 ListenableFuture 实现类,
- 创建时不带任何结果;
- 所有阻塞在 get() 上的线程会被立刻唤醒且拿到结果;
- 可以在任意时刻调用 set(V) 或 setException(Throwable) 把它标记为成功或失败
| 方法 | 作用 |
|---|
static <V> SettableFuture<V> create() | 新建一个未完成的实例 |
boolean set(V value) | 手动填成功结果;返回 true(false 表示已被 set) |
boolean setException(Throwable t) | 手动填异常;返回 true |
boolean cancel(boolean mayInterruptIfRunning) | 同父接口,也可直接取消 |
SettableFuture<Data> future = SettableFuture.create();
new Thread(() -> {try {Data data = future.get(); process(data);} catch (ExecutionException e) {handleError(e.getCause());}
}).start();
new Thread(() -> {Data data = longTimeCompute();future.set(data);
}).start();
八、CompletableFuture和ListenableFuture比较
| 维度 | CompletableFuture (JDK 8+) | ListenableFuture (Guava) |
|---|
| 所属库 | 官方 JDK (java.util.concurrent) | Google Guava |
| 核心能力 | Future + 链式阶段 (CompletionStage) | Future + 监听器 |
| 链式操作 | 内置 thenApply/thenCompose/handle/exceptionally | 需 Futures.transform/addListener |
| 异常处理 | 链内传播 handle/exceptionally | 手动 Futures.catching |
| 多任务合并 | allOf/anyOf/thenCombine | Futures.allAsList/successfulAsList |
| 异步执行 | 默认 ForkJoinPool(可自定义) | 必须传 Executor |
| 非阻塞回调 | 原生支持 | 需指定 Executor |
| 取消/超时 | orTimeout/completeOnTimeout(JDK 9+) | 需 ScheduledExecutor |
| 兼容旧 JDK | ≥ JDK 8 | ≥ JDK 7 |
| 依赖体积 | 0(官方) | + Guava jar |
| 学习成本 | 低(官方文档+社区大) | 中(Guava API 文档) |
一句话选型
JDK 8+ 新项目 → CompletableFuture(功能全、零依赖、社区大);
老系统/已深度用 Guava → ListenableFuture(无缝衔接,但链式能力稍弱)。
以上来自GPT,Future可学习的还有很多,比如链式操作、多任务合并等。
九、MoreExecutors.directExecutor()
- 在学习的过程中见到了MoreExecutors.directExecutor();
- Guava 提供的 “当前线程执行器”;
- 作用:不切换线程,任务在哪条线程提交,就在哪条线程立即运行——零延迟、零线程切换、零上下文开销。
- 代码实现:直接返回当前Executor

- 使用场景:
- 轻量级回调:只打印日志等