yohhoyの日記

技術的メモをしていきたい日記

java.util.concurrent.CompletableFutureクラス

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