completeablefuture katılmak vs get


93

Arasındaki fark nedir CompletableFuture.get()ve CompletableFuture.join()?

Kodum aşağıdadır:

List<String> process() {

    List<String> messages = Arrays.asList("Msg1", "Msg2", "Msg3", "Msg4", "Msg5", "Msg6", "Msg7", "Msg8", "Msg9",
            "Msg10", "Msg11", "Msg12");
    MessageService messageService = new MessageService();
    ExecutorService executor = Executors.newFixedThreadPool(4);

    List<String> mapResult = new ArrayList<>();

    CompletableFuture<?>[] fanoutRequestList = new CompletableFuture[messages.size()];
    int count = 0;
    for (String msg : messages) {
        CompletableFuture<?> future = CompletableFuture
                .supplyAsync(() -> messageService.sendNotification(msg), executor).exceptionally(ex -> "Error")
                .thenAccept(mapResult::add);

        fanoutRequestList[count++] = future;
    }

    try {
        CompletableFuture.allOf(fanoutRequestList).get();
      //CompletableFuture.allOf(fanoutRequestList).join();
    } catch (InterruptedException | ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return mapResult.stream().filter(s -> !s.equalsIgnoreCase("Error")).collect(Collectors.toList());
}

Her iki yöntemle de denedim ama sonuçta bir fark görmüyorum.


10
get()kontrol edilen istisnaları yakalamanızı gerektirir. Eğer değiştirmek zaman fark olmalıdır get()için join()size imediately ne olduğunu söyleyen bir derleyici hatası alırsınız olarak, InterruptedExceptionne de ExecutionExceptionatılmış olan trybloğun.
Holger

5
@ holi-java: join()kesintiye uğratılamaz.
Holger

@Holger evet efendim. Görevi yarıda kesemeyeceğimi fark ettim.
holi-java

9
Eh get, varolduğundan CompletableFutureuygular Futurebunu emreder arayüzü. join()büyük olasılıkla, futures'ları birleştirirken lambda ifadelerinde kontrol edilen istisnaları yakalama ihtiyacından kaçınmak için tanıtılmıştır. Diğer tüm kullanım durumlarında, tercih ettiğiniz her şeyi kullanmaktan çekinmeyin.
Holger

1
Join kullanmak veya iş parçacığında her iki blok olarak almak gerçekten mantıklı mı? Bunun yerine, eşzamansız işlevler zinciri oluşturmak için başka birleştirme yöntemlerini kullanarak bunu eşzamansız hale getiremez miyiz? Ancak örneğin ilkbaharda denetleyici yöntemi tarafından çağrılan ve tamamlanabilir bir gelecek döndüren bir hizmet yöntemi söz konusu olduğunda, hizmete alma veya katılma yöntemini çağırmamak daha mantıklı olur.
Shailesh Vaishampayan

Yanıtlar:


107

tek fark, yöntemlerin istisnaları nasıl attığıdır. arayüzde get()şu şekilde beyan Futureedilir:

V get() throws InterruptedException, ExecutionException;

İstisnaların her ikisi de işaretli istisnalardır, yani kodunuzda ele alınmaları gerekir. Kodunuzda görebileceğiniz gibi, IDE'nizdeki otomatik bir kod oluşturucu sizin adınıza dene-yakala bloğu oluşturup oluşturmayacağınızı sordu.

try {
  CompletableFuture.allOf(fanoutRequestList).get() 
} catch (InterruptedException | ExecutionException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

join()Yöntem atmaz kontrol istisnalar.

public T join()

Bunun yerine, denetlenmemiş CompletionException'ı atar . Böylece, bir dene-yakala bloğuna ihtiyacınız yoktur ve bunun yerine exceptionally(), çözülmüş List<String> processişlevi kullanırken yöntemi tam olarak kullanabilirsiniz.

CompletableFuture<List<String>> cf = CompletableFuture
    .supplyAsync(this::process)
    .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException
    .thenAccept(this::processFurther);

Her ikisini de get()ve join()uygulamayı burada bulabilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.