2014-12-31 15 views
19

Bir şey onaylamak gerekiyor. Aşağıdaki kodu:CompletableFuture, supplyAsync() ve thenApply()

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

Sağ:

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

aynı olurdu? thenApply'u neden kullanmamızın bir nedeni var: 1) dönüşüm için büyük bir kod mu yoksa 2) lambda bloğunu başka yerlerde yeniden kullanmak zorunda mı?

cevap

38

aynı şey değil değil. thenApply'un kullanılmadığı ikinci örnekte,numaralı aramanın, doSomethingAndReturnA yöntemiyle aynı iş parçacığında yürütüldüğü kesindir.

Ancak, ilk örnekte thenApply yönteminin kullanıldığı durumlarda başka şeyler olabilir.

Her şeyden önce, doSomethingAndReturnA'u yürüten CompletableFuture tamamlanmışsa, thenApply çağrıları arayan iş parçacığında gerçekleşir. CompletableFutures tamamlanamadıysa 'a iletilen Function, doSomethingAndReturnA ile aynı iş parçacığında çağrılır.

Kafa karıştırıcı? Eh this article might be helpful (link için @SotiriosDelimanolis teşekkürler).

thenApply'un nasıl çalıştığını gösteren kısa bir örnek verdim.

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"; 
    } 
} 

ve çıktısı:

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

birinci çalışma (yani CompletableFuture henüz tamamlanmamış) yavaş Yani, iki arama aynı iplik ortaya çıkar. Biz doSomethingAndReturnA çıktı Thread.sleep çağırın kaldırmak durumunda Ancak böyle olması (olabilir): convertToB çağrı main parçacığı olduğunu

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

Not söyledi.

+1

Bu yanıt ve bu ileti (http://www.deadcoderising.com/java8-writing-asynchronous-code-with -completablefuture /) CompletableFuture – Jesus

+0

'un anlaşılmasında bana yardımcı oluyor Bu hala birinin neden "thenApply" kullanacağını açıklamıyor? – Yamcha

+0

İlk durumda, '' 'ForkJoinPool.commonPool-worker-1''' sadece orada asılı ve '' doSomethingAndReturnA''' geri dönene kadar beklemek? – Siddhartha

2

thenApply(), supplyAsync() bir değer döndürdüğünde yürütülecek bir geri arama işlevidir.

Kod snippet 2'de, doSomethingAndReturnA() işlevine çağrılan iş parçacığı, işlevin yürütülmesini ve geri gönderilmesini bekler. Ancak bazı istisnai durumlarda (webservice çağrısı yapmak ve cevap beklemek gibi), iş parçacığı yanıtı almak için daha uzun süre beklemek zorundadır, bu da sistem kaynaklarını çok tüketir (yalnızca yanıt beklerken).

Bunu yapmak için, tamamlanabilir gelecek, geri çağrılma özelliği ile birlikte gelir; burada doSomethingAndReturnA() çağrıldığında, doSomethingAndReturnA() işlevini yürütmek için ayrı bir iş parçacığı ilgilenir ve ana arayan iş parçacığı beklemeden diğer işlemleri yapmaya devam eder. cevap verilecek. DoSomethingAndReturnA yanıtı alındıktan sonra, geri arama yöntemi çağrılır (yani, o zaman())