2014-12-31 9 views
19

何かを確認する必要があります。次のコード:CompletableFuture、supplyAsync()、thenApply()

CompletableFuture 
    .supplyAsync(() -> { 
     A a = doSomethingAndReturnA(); 
     convertToB(a); 
}); 

右:

CompletableFuture 
    .supplyAsync(() -> {return doSomethingAndReturnA();}) 
    .thenApply(a -> convertToB(a)); 

は同じでしょうか?私たちがthenApplyを使用する理由はありますか?1)変換のために大きなコードを持つか、2)他の場所でラムダブロックを再利用する必要がありますか?

答えて

38

同じものではないです。 2番目の例では、thenApplyを使用しない場合は、convertToBへの呼び出しがメソッドdoSomethingAndReturnAと同じスレッドで実行されていることが確認されています。

しかし、thenApplyメソッドが使用されたときの最初の例では、他のことが起こる可能性があります。

まず、doSomethingAndReturnAを実行するCompletableFutureが完了すると、thenApplyの呼び出しが呼び出し元スレッドで行われます。 CompletableFuturesが完了していない場合はthenApplyに渡されたFunctiondoSomethingAndReturnAと同じスレッドで呼び出されます。

混乱しますか?よくthis article might be helpful(リンクのために@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を削除した場合には、このようなこと(あり):convertToB呼び出しはmainスレッドであることを

doSomethingAndReturnA: ForkJoinPool.commonPool-worker-1 
convertToB: main 

注意。

+1

この回答とこの投稿(http://www.deadcoderising.com/java8-writing-asynchronous-code-with) -completablefuture /)CompletableFutureを理解するために助けてください – Jesus

+0

これはなぜ、なぜ「thenApply」を使うのか説明していませんか? – Yamcha

+0

最初のケースでは、 '' 'ForkJoinPool.commonPool-worker-1'''は' 'doSomethingAndReturnA'''が返るまで待っていますか? – Siddhartha

2

thenApply()はコールバック関数で、これは、supplyAsync()が値を返すときに実行されます。

コードスニペット2では、doSomethingAndReturnA()を呼び出したスレッドは、関数が実行されてデータを返すのを待ちます。しかし、例外的な場合(Webサービスの呼び出しや応答待ちなど)には、スレッドは応答を取得するのに長い時間を待たなければならず、システムリソースを大量に消費します。

doSomethingAndReturnA()が呼び出されると別のスレッドがdoSomethingAndReturnA()を実行し、メインの呼び出し元スレッドはその呼び出しを待たずに他の操作を続けます。返される応答。 doSomethingAndReturnAの応答が利用可能になると、コールバックメソッドが呼び出されます(すなわち、thenApple())

関連する問題