Contents

Java 9 中 CompletableFuture的改进

1. 简介

Java 9 对CompletableFuture类进行了一些更改。这些更改是作为JEP 266 的一部分引入的,以解决自 JDK 8 中引入以来的常见抱怨和建议,更具体地说,是对延迟和超时的支持,对子类化的更好支持和一些实用方法。

在代码方面,该 API 带有 8 个新方法和 5 个新静态方法。为了启用此类添加,大约 2400 行代码中的 1500 行被更改(根据 Open JDK)。

2. 实例 API 添加

如前所述,实例 API 有八个新增功能,它们是:

  1. Executor defaultExecutor()
  2. CompletableFuture<U> newIncompleteFuture()
  3. CompletableFuture<T> copy()
  4. CompletionStage<T> minimalCompletionStage()
  5. CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
  6. CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
  7. CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)
  8. 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 添加

还添加了一些实用方法。他们是:

  1. Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
  2. Executor delayedExecutor(long delay, TimeUnit unit)
  3. <U> CompletionStage<U> completedStage(U value)
  4. <U> CompletionStage<U> failedStage(Throwable ex)*
  5. <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. completedStagefailedStage方法

<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);