Java 9 CompletableFuture 進化小腳步

油膩的Java發表於2019-04-04

簡介

Java 9附帶了對CompletableFuture類的一些更改。這些更改是作為JEP 266的一部分引入的,以便解決自JDK 8引入以來的一些問題,更具體地說,支援延遲和超時,抽象出一個工具類和一些實用方法。

程式碼方面,API提供了八種新方法和五種新的靜態方法。根據Open JDK描述,為了實現這樣的新增,大約2400個程式碼行中的1500處被更改。

例項API新增

如上所述,例項API附帶了八個新增功能,它們是:

  • Executor defaultExecutor()
  • CompletableFuture newIncompleteFuture()
  • CompletableFuture copy()
  • CompletionStage minimalCompletionStage()
  • CompletableFuture completeAsync(Supplier<? extends T> supplier, Executor executor)
  • CompletableFuture completeAsync(Supplier<? extends T> supplier)
  • CompletableFuture orTimeout(long timeout, TimeUnit unit)
  • CompletableFuture completeOnTimeout(T value, long timeout, TimeUnit unit)

defaultExecutor()方法

API

Executor defaultExecutor()
複製程式碼

返回預設的Executor用於那些沒有指定非同步方法的呼叫者。

new CompletableFuture().defaultExecutor()

複製程式碼

這可以由返回執行執行緒的子類覆蓋,該執行執行緒至少提供一個獨立的執行緒。

newIncompleteFuture()方法

API

CompletableFuture <U> newIncompleteFuture()
複製程式碼

該newIncompleteFuture,也被稱為“虛擬建構函式”,是用來獲得相同型別的新completable例項。

new CompletableFuture().newIncompleteFuture()
複製程式碼

當子類化CompletableFuture時,此方法特別有用,主要是因為它幾乎在所有返回新的CompletionStage的方法內部使用,允許子類控制此類方法返回的子型別。

copy()方法

API

CompletableFuture <T> copy()
複製程式碼

此方法返回一個新的CompletableFuture,其中:

當原來的CompletableFuture是執行正常的,那麼copy之後的CompletableFuture也會是正常的。

當原來的CompletableFuture丟擲了異常 Exception X,那麼copy之後的CompletableFuture也會出現 Exception X

new CompletableFuture().copy()
複製程式碼

此方法可用作“防禦性複製”的形式,能夠在CompletableFuture的特定例項上安排依賴操作。

minimalCompletionStage()方法

API

CompletionStage <T> minimalCompletionStage()
複製程式碼

此方法返回一個新的CompletionStage,其行為方式與copy方法描述的完全相同,然而,在每次嘗試檢索或設定已解析的值時,此類新例項都會丟擲UnsupportedOperationException。

new CompletableFuture().minimalCompletionStage()
複製程式碼

可以使用CompletionStage API 上提供的toCompletableFuture方法檢索具有所有可用方法的新CompletableFuture。

completeAsync()方法

該completeAsync方法應當用於完成CompletableFuture非同步使用由給定的值Supplier提供。

API

CompletableFuture<T> completeAsync(Supplier<? extends T> supplier, Executor executor)
CompletableFuture<T> completeAsync(Supplier<? extends T> supplier)
複製程式碼

這兩個過載方法之間的區別在於存在第二個引數,其中可以指定執行任務的Executor。如果未提供,則將使用預設執行程式(由defaultExecutor方法返回)。

orTimeout()方法

API

CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)
複製程式碼
new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)
複製程式碼

除非在指定的超時之前完成CompletableFuture,否則使用TimeoutException異常解析CompletableFuture。

completeOnTimeout()方法

API

CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)
複製程式碼
new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)
複製程式碼

除非在指定的超時之前完成,否則通常使用指定的值完成CompletableFuture。

static API

還新增了一些實用方法。他們是:

  • Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
  • Executor delayedExecutor(long delay, TimeUnit unit)
  • CompletionStage completedStage(U value)
  • CompletionStage failedStage(Throwable ex)
  • CompletableFuture failedFuture(Throwable ex)

方法延遲執行

Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
Executor delayedExecutor(long delay, TimeUnit unit)
複製程式碼

返回一個新的Executor,它在給定的延遲之後將任務提交給給定的基本執行程式(如果非正數則沒有延遲)。每次延遲都在呼叫返回的執行程式的execute方法時開始。如果未指定執行程式,則將使用預設執行程式(ForkJoinPool.commonPool())。

方法completedStage和failedStage

API

<U> CompletionStage<U> completedStage(U value)
<U> CompletionStage<U> failedStage(Throwable ex)
複製程式碼

此實用程式方法返回已解析的CompletionStage例項,這些例項通常使用值(completedStage)完成,或者使用給定的異常完成異常(failedStage)。

方法failedFuture

API

<U> CompletableFuture<U> failedFuture(Throwable ex)
複製程式碼

failedFuture方法新增了指定已完成的異常CompleatebleFuture例項的功能。

示例用例

將展示一些有關如何使用某些新API的示例。

Delay

此示例將說明如何將具有特定值的CompletableFuture的完成延遲一秒。這可以通過將completeAsync方法與delayedExecutor一起使用來實現。

CompletableFuture<Object> future = new CompletableFuture<>();
future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
複製程式碼

completeOnTimeout

實現延遲結果的另一種方法是使用completeOnTimeout方法。此示例定義了一個CompletableFuture,如果在1秒後仍未解析,則將使用給定輸入解析該CompletableFuture。

CompletableFuture<Object> future = new CompletableFuture<>();
future.completeOnTimeout(input, 1, TimeUnit.SECONDS);
複製程式碼

Timeout

另一種可能性是超時,它使用TimeoutException異常地解決了未來。例如,如果在此之前沒有完成,則在1秒後使CompletableFuture超時。

CompletableFuture<Object> future = new CompletableFuture<>();
future.orTimeout(1, TimeUnit.SECONDS);
複製程式碼

結論

總之,Java 9附帶了一些CompletableFuture API,它現在可以更好地支援子類化,由於newIncompleteFuture虛擬建構函式,可以控制大多數CompletionStage API中返回的CompletionStage例項。

如前所示,它肯定能更好地支援延遲和超時。新增的實用程式方法遵循合理的模式,為CompletableFuture提供了指定已解析例項的便捷方式。

相關文章