CompletableFuture手始め(先ずはFuture)
の続き
CompletableFuture
図の通り、CompletableFurure
は、
Future
、CompletionStage
インターフェースを実装している。
CompletionStage
はJava8で導入されたインターフェース。
CompletableFutureは、非同期処理を表し、利用可能となった時にその結果を保持する。
Futureとは何が違うのか?
CompletableFuture
明示的に(その値とステータスを設定して)完了できるFutureです。
その完了時に発生する依存関数およびアクションをサポートし、CompletionStageとして使用できます。
CompletableFuture@Oracle
この「完了時に発生する依存関数およびアクションをサポート」がCompletableFuture
の大きな特徴
Future
の特徴である、「時間のかかる処理で待たされることがなくなる」に加え、
以下のようなことが行える。
処理の結果が利用可能となった際、
通知を出したり、ラムダ式やメソッド参照により定義されたコールバックを実行したりすることができる。
基本的な使用法
public Future<Double> getDoubleAsync(String variable){
// 計算結果が保持されるCompletableFutureを作成
CompletableFuture<Double> futureValue = new CompletableFuture<>();
new Thread( () -> { // 別スレッドで処理を非同期で実行
try {
// 時間のかかる処理
double price = doSomeLongComputation(variable);
// 結果の値を設定
futureValue.complete(price);
} catch (Exception ex) {
futureValue.completeExceptionally(ex);
}
}).start();
// 計算を待つことなくFutureを返す
return futureValue;
}
上記メソッドの呼び出し方
// 戻り値の型は、Future<Double>
Future<Double> futureValue = getDoubleAsync("test");
try {
// ここで呼び出す。値が利用可能となっていなければブロックされる
double value = futureValue.get();
System.out.printf("value is %.2f%n", value);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
SupplyAsync
を使用する場合
CompletableFuture
クラスには、複数のファクトリーメソッドがある。
supplyAsync(Supplier supplier)
ForkJoinPool.commonPool()で実行されているタスクが指定されたサプライヤを呼び出して取得した値を使用して非同期的に完了する新しいCompletableFutureを返します。
supplyAsync@Oracke
public static Future<Double> getDoubleAsyncHandy(String arg) {
return CompletableFuture.supplyAsync(() -> doSomeLongComputation(arg));
}
supplyAsync
メソッドを使うと上記のように簡易にCompletableFuture
を書くことができる。