1. 引言
Java 9 对 CompletableFuture
类进行了一些重要改进。这些改进作为 JEP 266 的一部分引入,主要解决了自 JDK 8 引入以来的常见问题和建议,特别是增加了对延迟和超时的支持、优化了子类化能力并新增了若干实用方法。
从代码层面看,API 新增了 8 个实例方法和 5 个静态方法。根据 Open JDK 的统计,为实现这些功能,大约修改了 2400 行代码中的 1500 行。
2. 实例 API 新增方法
实例 API 新增了 8 个方法:
-
Executor defaultExecutor()
-
CompletableFuture<U> newIncompleteFuture()
-
CompletableFuture<T> copy()
-
CompletionStage<T> minimalCompletionStage()
-
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
-
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
-
CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)
-
CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)
2.1 defaultExecutor()
方法
签名:Executor defaultExecutor()
返回未指定 Executor
的异步方法所使用的默认执行器。
new CompletableFuture().defaultExecutor()
子类可以重写此方法,返回一个至少包含一个独立线程的执行器。
2.2 newIncompleteFuture()
方法
签名:CompletableFuture<U> newIncompleteFuture()
newIncompleteFuture
(又称"虚拟构造器")用于获取同类型的新 CompletableFuture
实例。
new CompletableFuture().newIncompleteFuture()
在子类化 CompletableFuture
时特别有用,因为它被几乎所有返回新 CompletionStage
的方法内部使用,允许子类控制这些方法返回的子类型。
2.3 copy()
方法
签名:CompletableFuture<T> copy()
返回一个新的 CompletableFuture
,其行为如下:
- 当原实例正常完成时,新实例也正常完成
- 当原实例因异常 X 异常完成时,新实例也以
CompletionException
(X 作为原因)异常完成
new CompletableFuture().copy()
此方法可用于"防御性复制",防止客户端直接完成操作,同时仍能在特定 CompletableFuture
实例上安排依赖操作。
2.4 minimalCompletionStage()
方法
签名:CompletionStage<T> minimalCompletionStage()
返回一个新的 CompletionStage
,行为与 copy()
方法描述完全相同,但新实例在尝试获取或设置解析值时会抛出 UnsupportedOperationException
。
new CompletableFuture().minimalCompletionStage()
可通过 CompletionStage
API 的 toCompletableFuture()
方法获取包含所有方法的完整 CompletableFuture
。
2.5 completeAsync()
方法
completeAsync
方法用于使用提供的 Supplier
给定的值异步完成 CompletableFuture
。
签名:
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
两个重载方法的区别在于第二个参数(指定运行任务的 Executor
)。未提供时将使用默认执行器(由 defaultExecutor()
返回)。
2.6 orTimeout()
方法
签名:CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)
new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)
若未在指定超时前完成,则以 TimeoutException
异常完成 CompletableFuture
。
2.7 completeOnTimeout()
方法
签名:CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)
new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)
若未在指定超时前完成,则以给定值正常完成 CompletableFuture
。
3. 静态 API 新增方法
新增了几个实用方法:
-
Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
-
Executor delayedExecutor(long delay, TimeUnit unit)
-
<U> CompletionStage<U> completedStage(U value)
-
<U> CompletionStage<U> failedStage(Throwable ex)
-
<U> CompletableFuture<U> failedFuture(Throwable ex)
3.1 delayedExecutor
方法
签名:
Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
Executor delayedExecutor(long delay, TimeUnit unit)
返回一个新的 Executor
,在给定延迟后将任务提交给基础执行器(非正延迟则无延迟)。每次延迟从调用返回执行器的 execute
方法开始计算。未指定执行器时使用默认执行器(ForkJoinPool.commonPool()
)。
3.2 completedStage
和 failedStage
方法
签名:
<U> CompletionStage<U> completedStage(U value)
<U> CompletionStage<U> failedStage(Throwable ex)
这些实用方法返回已解析的 CompletionStage
实例:completedStage
返回正常完成的实例,failedStage
返回以给定异常异常完成的实例。
3.3 failedFuture
方法
签名:<U> CompletableFuture<U> failedFuture(Throwable ex)
failedFuture
方法新增了指定已异常完成的 CompletableFuture
实例的能力。
4. 实用场景示例
本节展示如何使用部分新 API。
4.1 延迟操作
此示例展示如何延迟 1 秒后用特定值完成 CompletableFuture
。可通过 completeAsync
结合 delayedExecutor
实现:
CompletableFuture<Object> future = new CompletableFuture<>();
future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
4.2 超时默认值
另一种实现延迟结果的方式是使用 completeOnTimeout
。此示例定义一个 CompletableFuture
,若 1 秒内未完成,则解析为给定输入值:
CompletableFuture<Object> future = new CompletableFuture<>();
future.completeOnTimeout(input, 1, TimeUnit.SECONDS);
4.3 超时异常
另一种可能是超时触发异常完成(以 TimeoutException
)。例如,让 CompletableFuture
在 1 秒后超时(若之前未完成):
CompletableFuture<Object> future = new CompletableFuture<>();
future.orTimeout(1, TimeUnit.SECONDS);
5. 总结
Java 9 为 CompletableFuture
API 带来了多项改进:
✅ 通过 newIncompleteFuture
虚拟构造器优化了子类化支持
✅ 新增了延迟和超时处理能力
✅ 实用方法遵循合理模式,简化了已解析实例的创建
这些改进使 CompletableFuture
在异步编程中更加灵活和健壮。本文示例代码可在 GitHub 仓库 中找到。