Qual é a diferença entre CompletableFuture.get()
e CompletableFuture.join()
?
Abaixo está o meu código:
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());
}
Eu tentei com os dois métodos, mas não vejo diferença no resultado.
java
java-8
completable-future
Nomeswaran
fonte
fonte
get()
requer que você capture exceções verificadas. Você deve notar a diferença ao mudar deget()
parajoin()
, pois imediatamente obterá um erro do compilador dizendo que nemInterruptedException
e nemExecutionException
são lançados notry
bloco.join()
não pode ser interrompido.get
existe, porqueCompletableFuture
implementa aFuture
interface que o exige.join()
provavelmente foi introduzido, para evitar a necessidade de capturar exceções verificadas em expressões lambda ao combinar futuros. Em todos os outros casos de uso, fique à vontade para usar o que preferir.Respostas:
a única diferença é como os métodos lançam exceções.
get()
é declarado naFuture
interface comoV get() throws InterruptedException, ExecutionException;
As exceções são exceções verificadas, o que significa que precisam ser tratadas em seu código. Como você pode ver em seu código, um gerador automático de código em seu IDE perguntou se deveria criar o bloco try-catch em seu nome.
try { CompletableFuture.allOf(fanoutRequestList).get() } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }
O
join()
método não lança exceções verificadas .public T join()
Em vez disso, ele lança CompletionException desmarcado . Portanto, você não precisa de um bloco try-catch e, em vez disso, pode aproveitar totalmente o
exceptionally()
método ao usar aList<String> process
função disscusedCompletableFuture<List<String>> cf = CompletableFuture .supplyAsync(this::process) .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException .thenAccept(this::processFurther);
Você pode encontrar ambos
get()
ejoin()
implementação aquifonte