completablefuture join vs get

Nomeswaran picture Nomeswaran · Aug 3, 2017 · Viewed 39k times · Source

What is the difference between CompletableFuture.get() and CompletableFuture.join() ?

Below is the my code:

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());
}

I have tried with both methods but I see no difference in result.

Answer

Dawid Wr&#243;blewski picture Dawid Wróblewski · Nov 23, 2017

the only difference is how methods throw exceptions. get() is declared in Future interface as

V get() throws InterruptedException, ExecutionException;

The exceptions are both checked exceptions which means they need to be handled in your code. As you can see in your code an automatic code generator in your IDE asked if to creat try-catch block on your behalf.

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

The join() method doesn't throw checked exceptions.

public T join()

Instead it throws unchecked CompletionException. So you do not need a try-catch block and instead you can fully harness exceptionally() method when using the disscused List<String> process function

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

You can find both get() and join() implementation here