何か確認する必要があります。次のコード:
CompletableFuture
.supplyAsync(() -> {return doSomethingAndReturnA();})
.thenApply(a -> convertToB(a));
次と同じです:
CompletableFuture
.supplyAsync(() -> {
A a = doSomethingAndReturnA();
convertToB(a);
});
右?
さらに、「thenApply
を使用する理由はありますか?」に関する次の2つの質問があります。
1)変換用の大きなコードを持っていますか?
または
2)ラムダブロックを他の場所で再利用する必要がありますか?
同じものではありません。 thenApply
が使用されない2番目の例では、convertToB
への呼び出しがメソッドdoSomethingAndReturnA
と同じスレッドで実行されることが確実です。
ただし、最初の例では、thenApply
メソッドを使用すると、他のことが起こります。
まず、CompletableFuture
を実行するdoSomethingAndReturnA
が完了すると、呼び出し元のスレッドでthenApply
の呼び出しが行われます。 CompletableFutures
が完了していない場合、Function
に渡されたthenApply
は、doSomethingAndReturnA
と同じスレッドで呼び出されます。
紛らわしい?よく この記事は役に立つかもしれません (リンクについて@SotiriosDelimanolisに感謝します)。
thenApply
がどのように機能するかを示す短い例を提供しました。
public class CompletableTest {
public static void main(String... args) throws ExecutionException, InterruptedException {
final CompletableFuture<Integer> future = CompletableFuture
.supplyAsync(() -> doSomethingAndReturnA())
.thenApply(a -> convertToB(a));
future.get();
}
private static int convertToB(final String a) {
System.out.println("convertToB: " + Thread.currentThread().getName());
return Integer.parseInt(a);
}
private static String doSomethingAndReturnA() {
System.out.println("doSomethingAndReturnA: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "1";
}
}
出力は次のとおりです。
doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: ForkJoinPool.commonPool-worker-1
そのため、最初の操作が遅い(つまり、CompletableFuture
がまだ完了していない)場合、両方の呼び出しが同じスレッドで発生します。ただし、doSomethingAndReturnA
からThread.sleep
- callを削除する場合、出力は(おそらく)次のようになります。
doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1
convertToB: main
convertToB
呼び出しはmain
スレッド内にあることに注意してください。
thenApply()
はコールバック関数であり、supplyAsync()
が値を返すときに実行されます。
コードスニペット2では、doSomethingAndReturnA()
を呼び出したスレッドは、関数が実行されてデータが返されるまで待機します。
しかし、いくつかの例外的なケース(Webサービスの呼び出しや応答の待機など)では、スレッドは応答を取得するためにlong時間待機する必要があり、システムの計算リソースを大量に消費します(応答を待機するだけです) 。
それを避けるために、CompletableFuture
にはcallback機能が付属しています。この機能では、doSomethingAndReturnA()
が呼び出されると、別のスレッドがdoSomethingAndReturnA()
の実行を処理します。そして、メインの呼び出し元スレッドは、応答が戻るのを待たずに他の操作を続けます。
doSomethingAndReturnA
の応答が利用可能になると、コールバックメソッドが呼び出されます(つまり、thenApply()
)