Java 9 中 CompletableFuture的改进
1. 简介
Java 9 对CompletableFuture类进行了一些更改。这些更改是作为JEP 266 的一部分引入的,以解决自 JDK 8 中引入以来的常见抱怨和建议,更具体地说,是对延迟和超时的支持,对子类化的更好支持和一些实用方法。
在代码方面,该 API 带有 8 个新方法和 5 个新静态方法。为了启用此类添加,大约 2400 行代码中的 1500 行被更改(根据 Open JDK)。
2. 实例 API 添加
如前所述,实例 API 有八个新增功能,它们是:
- 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 的异步方法的默认Executor。
new CompletableFuture().defaultExecutor()
这可以被返回执行程序的子类覆盖,该执行程序至少提供一个独立线程。
2.2. *newIncompleteFuture()*方法
newIncompleteFuture也称为“虚拟构造函数”,用于获取相同类型的新的可完成未来实例。
new CompletableFuture().newIncompleteFuture()
这个方法在子类化CompletableFuture时特别有用,主要是因为它在几乎所有返回新CompletionStage的方法中都在内部使用,允许子类控制这些方法返回的子类型。
2.3. *copy()*方法
此方法返回一个新的CompletableFuture,它:
- 当这正常完成时,新的也正常完成
- 当这以异常 X 异常完成时,新的异常也以 X 为原因的CompletionException异常完成
new CompletableFuture().copy()
这种方法作为“防御性复制”的一种形式可能很有用,以防止客户端完成,同时仍然能够在CompletableFuture的特定实例上安排相关操作。
2.4. *minimumCompletionStage()*方法
此方法返回一个新的CompletionStage,其行为方式与复制方法描述的完全相同,但是,此类新实例在每次尝试检索或设置解析值时都会引发UnsupportedOperationException。
new CompletableFuture().minimalCompletionStage()
可以使用CompletionStage API上可用的toCompletableFuture方法检索具有所有可用方法的新CompletableFuture。
2.5. *completeAsync()*方法
应该使用 completeAsync 方法使用提供者提供的值异步完成CompletableFuture。
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
这两个重载方法的区别在于存在第二个参数,其中可以指定运行任务的Executor。如果没有提供,将使用默认执行器(由defaultExecutor方法返回)。
2.6. *orTimeout()*方法
new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)
使用TimeoutException异常解决CompletableFuture,除非它在指定的超时之前完成。
2.7. *completeOnTimeout()*方法
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,它在给定的延迟(如果非正则没有延迟)之后将任务提交给给定的基本执行器。每次延迟都在调用返回的执行程序的执行方法时开始。如果未指定执行程序,则将使用默认执行程序(ForkJoinPool.commonPool())。
3.2. completedStage和failedStage方法
<U> CompletionStage<U> completedStage(U value)
<U> CompletionStage<U> failedStage(Throwable ex)
此实用程序方法返回已解析的CompletionStage实例,可以正常完成并带有值 ( completedStage ) 或异常完成 ( failedStage ) 并带有给定的异常。
3.3. failedFuture方法
failedFuture 方法增加了指定已经完成的异常CompleatebleFuture实例的能力。
4. 示例用例
在本节中,将展示一些有关如何使用某些新 API 的示例。
4.1. 延迟
此示例将展示如何将具有特定值的CompletableFuture的完成延迟一秒。这可以通过将completeAsync方法与delayExecutor一起使用来实现。
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);