Java 9 CompletableFuture APIの改善

Java 9 CompletableFuture APIの改善

1. 前書き

Java 9では、CompletableFutureクラスにいくつかの変更が加えられています。 このような変更は、JDK 8での導入以降、一般的な苦情や提案に対処するためにJEP 266の一部として導入されました。具体的には、遅延とタイムアウトのサポート、サブクラス化のサポートの改善、およびいくつかのユーティリティメソッドです。

コード面では、APIには8つの新しいメソッドと5つの新しい静的メソッドが付属しています。 このような追加を可能にするために、2400行のコードのうち約1500行が変更されました(Open JDKによる)。

2. インスタンスAPIの追加

前述のように、インスタンスAPIには次の8つの新しい追加機能があります。

  1. エグゼキュータdefaultExecutor()

  2. CompletableFuture newIncompleteFuture()

  3. CompletableFuture copy()

  4. CompletionStage minimumCompletionStage()

  5. CompletableFuture completeAsync(Supplier <? T>サプライヤー、エグゼキューターエグゼキューターを拡張します)

  6. CompletableFuture completeAsync(Supplier <? T>サプライヤーを拡張)

  7. CompletableFuture またはTimeout(長いタイムアウト、TimeUnit単位)

  8. CompletableFuture completeOnTimeout(T値、長いタイムアウト、TimeUnit単位)

2.1. メソッドdefaultExecutor()

SignatureExecutor defaultExecutor()

Executorを指定しない非同期メソッドに使用されるデフォルトのExecutorを返します。

new CompletableFuture().defaultExecutor()

これは、少なくとも1つの独立したスレッドを提供するエグゼキューターを返すサブクラスによってオーバーライドできます。

2.2. メソッドnewIncompleteFuture()

SignatureCompletableFuture<U> newIncompleteFuture()

「仮想コンストラクター」とも呼ばれるnewIncompleteFutureは、同じタイプの新しい完了可能な将来のインスタンスを取得するために使用されます。

new CompletableFuture().newIncompleteFuture()

このメソッドは、CompletableFutureをサブクラス化するときに特に役立ちます。これは、主に、新しいCompletionStageを返すほとんどすべてのメソッドで内部的に使用され、サブクラスがそのようなメソッドによって返されるサブタイプを制御できるためです。

2.3. メソッドcopy()

SignatureCompletableFuture<T> copy()

このメソッドは、次のような新しいCompletableFutureを返します。

  • これが正常に完了すると、新しいものも正常に完了します

  • これが例外Xを除いて例外的に完了すると、新しいものも例外的に完了し、CompletionExceptionが原因としてXが使用されます

new CompletableFuture().copy()

このメソッドは、CompletableFutureの特定のインスタンスに依存するアクションを配置できる一方で、クライアントが完了しないようにするための「防御コピー」の形式として役立つ場合があります。

2.4. メソッドminimalCompletionStage()

SignatureCompletionStage<T> minimalCompletionStage()

このメソッドは、copyメソッドで説明されているのとまったく同じように動作する新しいCompletionStageを返しますが、このような新しいインスタンスは、解決された値を取得または設定しようとするたびにUnsupportedOperationExceptionをスローします。

new CompletableFuture().minimalCompletionStage()

利用可能なすべてのメソッドを備えた新しいCompletableFutureは、CompletionStage APIで利用可能なtoCompletableFutureメソッドを使用して取得できます。

2.5. メソッドcompleteAsync()

completeAsyncメソッドは、提供されたSupplierによって指定された値を使用して、CompletableFutureを非同期的に完了するために使用する必要があります。

Signatures

CompletableFuture completeAsync(Supplier supplier, Executor executor)
CompletableFuture completeAsync(Supplier supplier)

この2つのオーバーロードされたメソッドの違いは、タスクを実行しているExecutorを指定できる2番目の引数の存在です。 何も指定されていない場合は、デフォルトのエグゼキュータ(defaultExecutorメソッドによって返される)が使用されます。

2.6. メソッドorTimeout()

SignatureCompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)

指定されたタイムアウトの前に完了しない限り、CompletableFutureTimeoutExceptionで例外的に解決します。

2.7. メソッドcompleteOnTimeout()

SignatureCompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)

指定されたタイムアウトの前に完了しない限り、CompletableFutureを指定された値で正常に完了します。

3. 静的APIの追加

いくつかのユーティリティメソッドも追加されました。 彼らです:

  1. エグゼキュータdelayedExecutor(長い遅延、TimeUnitユニット、エグゼキュータエグゼキュータ)

  2. エグゼキュータdelayedExecutor(長い遅延、TimeUnit単位)

  3. CompletionStage completeStage(U value)

  4. CompletionStage failedStage(Throwable ex)

  5. CompletableFuture failedFuture(Throwable ex)

3.1. メソッドdelayedExecutor

Signatures

Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
Executor delayedExecutor(long delay, TimeUnit unit)

指定された遅延(または正でない場合は遅延なし)の後に、指定されたベースエグゼキュータにタスクを送信する新しいExecutorを返します。 各遅延は、返されたエグゼキュータのexecuteメソッドの呼び出しで始まります。 エグゼキュータが指定されていない場合、デフォルトのエグゼキュータ(ForkJoinPool.commonPool())が使用されます。

3.2. メソッドcompletedStageおよびfailedStage

Signatures

 CompletionStage completedStage(U value)
 CompletionStage failedStage(Throwable ex)

このユーティリティメソッドは、すでに解決されたCompletionStageインスタンスを返します。値(completedStage)で正常に完了するか、指定された例外を除いて例外的に完了します(failedStage)。

3.3. メソッドfailedFuture

Signature<U> CompletableFuture<U> failedFuture(Throwable ex)

failedFutureメソッドは、すでに完了した例外的にCompleatebleFutureインスタンスを指定する機能を追加します。

4. ユースケースの例

このセクションでは、新しいAPIの使用方法の例をいくつか示します。

4.1. ディレイ

この例では、特定の値を持つCompletableFutureの完了を1秒遅らせる方法を示します。 これは、completeAsyncメソッドをdelayedExecutorと一緒に使用することで実現できます。

CompletableFuture future = new CompletableFuture<>();
future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));



4.2. タイムアウト時の値で完了

遅延結果を達成する別の方法は、completeOnTimeoutメソッドを使用することです。 この例では、1秒後に未解決のままである場合に、指定された入力で解決されるCompletableFutureを定義します。

CompletableFuture future = new CompletableFuture<>();
future.completeOnTimeout(input, 1, TimeUnit.SECONDS);



4.3. タイムアウト

もう1つの可能性は、TimeoutExceptionで例外的に将来を解決するタイムアウトです。 たとえば、CompletableFutureが1秒後にタイムアウトすると、その前に完了しません。

CompletableFuture future = new CompletableFuture<>();
future.orTimeout(1, TimeUnit.SECONDS);





5. 結論

結論として、Java 9にはCompletableFuture APIにいくつかの追加機能があり、newIncompleteFuture仮想コンストラクターのおかげで、サブクラス化のサポートが向上し、CompletionStageを制御できるようになりました。ほとんどのCompletionStageAPIでインスタンスが返されました。

前に示したように、遅延とタイムアウトのサポートは間違いなく優れています。 追加されたユーティリティメソッドは適切なパターンに従い、CompletableFutureに解決されたインスタンスを指定する便利な方法を提供します。

この記事で使用されている例は、GitHub repositoryにあります。