Java8で追加された java.util.concurrent.CompletableFuture*1 クラスについてメモ。CompletionStage, Futureの両インタフェースを実装するクラス。
Executorsフレームワーク(Java5以降)およびFork/Joinフレームワーク(Java7以降)の上で、Futureパターン*2により合成可能な非同期/同期処理を実装するためのユーティリティクラス。類似のFutureTaskクラスは単なる同期プリミティブに過ぎないが、CompletableFutureクラスは独立した1つのフレームワークともいえる機能を提供する。
- CompletableFuture<T>オブジェクトは、戻り値がT型オブジェクトまたは任意の例外送出の処理結果を表す。*3(Futureインタフェース)
- 実処理本体としてRunnable(T=Void)、またはSupplier/Function/Consumerインタフェースを指定する。いずれも関数型インタフェースのため処理をラムダ式として記述可能。
- ある処理結果の完了を待機、完了の問い合わせ、処理キャンセル要求などを行える。
- 任意の処理が完了した後に続継実行される、別の処理を連結できる。(CompletionStageインタフェース)
- 非同期/同期処理を選択可能なメソッドオーバーロードを提供する。非同期型の場合は指定ExecutorまたはFork/Joinフレームワーク*4上で、同期型の場合は同一スレッド上で継続処理が実行される。
ノート:Stream APIはデータ並列の記述に向いている一方、CompletableFutureはタスク並列の記述に向いている。両者ともFork/Joinフレームワーク上で動作するため併用もできる。
CompletableFutureクラスは60個近いメソッドを提供するが、それらを「オブジェクト生成」「結果アクセス」「処理合成」とその他メソッドに大別して列挙する。
オブジェクト生成
staticメソッド名 | 概要 |
---|---|
(コンストラクタ) | 未完了のオブジェクトを生成 |
runAsync | Runnableを非同期実行するオブジェクト(T=Void)を生成 |
supplyAsync | Supplier<U>を非同期実行するオブジェクト(T=U)を生成 |
completedFuture | U型の結果オブジェクトによる正常完了済みオブジェクト(T=U)を生成 |
結果アクセス
メソッド名 | 概要 |
---|---|
complete | 未完了ならば結果オブジェクトによる正常完了を設定 |
completeExceptionally | 未完了ならば例外オブジェクトによる例外完了を設定 |
cancel | 未完了ならばキャンセル完了を設定 |
obtrudeValue | 強制的に結果オブジェクトによる正常完了を設定 |
obtrudeException | 強制的に例外オブジェクトによる例外完了を設定 |
isDone | 理由によらず処理完了済みか否かを返す |
isCompletedExceptionally | 例外完了により完了済みか否かを返す |
isCancelled | キャンセル完了により完了済みか否かを返す |
get | 完了を待機し結果オブジェクトを返す(タイムアウト指定も可能) |
join | 完了を待機し結果オブジェクトを返す |
getNow | 完了済みなら結果オブジェクトを、未完了ならば指定値を即座に返す |
getメソッドではキャンセル完了のみ非検査例外CancellationException、例外完了は検査例外ExecutionExceptionとなっている。一方でjoin, getNotメソッドの例外完了は非検査例外CompletionExceptionを送出する。
処理合成
下表中の同期処理版xxxXxxメソッドに対して、それぞれ非同期処理版xxxXxxAsyncメソッドが存在する(exceptionally, allOf, anyOfメソッドを除く)。
メソッド名 | 概要 |
---|---|
t0.thenRun(r) | t0の正常完了後にRunnableを実行するオブジェクト(Void)を返す |
t0.thenAccept(c) | t0の正常完了後にCunsumer<T>を実行するオブジェクト(Void)を返す |
t0.thenApply(f) | t0の正常完了後にFunction<T,U>を実行するオブジェクト(U)を返す |
t0.thenCompose(f) | t0の正常完了後にFunction<T,CompletionStage<U>>を実行するオブジェクト(U)を返す |
t1.runAfterBoth(u1,r) | t1,u1両方が正常完了後にRunnableを実行するオブジェクト(Void)を返す |
t1.thenAcceptBoth(u1,bc) | t1,u1両方が正常完了後にBiCunsumer<T,U>を実行するオブジェクト(Void)を返す |
t1.thenCombime(u1,bf) | t1,u1両方が正常完了後にBiFunction<T,U,V>を実行するオブジェクト(V)を返す |
t1.runAfterEither(u1,r) | t1,u1いずれかが正常完了後にRunnableを実行するオブジェクト(Void)を返す |
t1.acceptEither(t2,c) | t1,t2いずれかが正常完了後にCunsumer<T>を実行するオブジェクト(Void)を返す |
t1.applyToEither(t2,f) | t1,t2いずれかが正常完了後にFunction<T,U>を実行するオブジェクト(U)を返す |
t0.exceptionally(f) | t0の例外完了後にFunction<Throwable,T>を実行するオブジェクト(T)を返す |
t0.whenComplete(bc) | t0の正常/例外完了後にBiCunsumer<T,Throwable>を実行するオブジェクト(Void)を返す |
t0.handle(bf) | t0の正常/例外完了後にBiFunction<Throwable,T,U>を実行するオブジェクト(U)を返す |
allOf(t...) | 全てのオブジェクト完了後に完了するオブジェクト(Void)を返す |
anyOf(t...) | いずれか1つのオブジェクト完了後に完了するオブジェクト(Object)を返す |
注:allOf, anyOfの2つはCompletableFutureクラスのstaticメソッド。
関連URL
*1:日本語版:http://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/CompletableFuture.html
*2:wikipedia:en:Futures_and_promises
*3:処理結果が検査例外(checked exception)の送出であっても、結果取得時には非検査例外java.util.concurrent.ExecutionExceptionにラップされて送出される。
*4:java.util.concurrent.ForkJoinPool.commonPool()が返すFork/Joinフレームワークの共通プールExecutor