¿Cuál es la diferencia entre CompletableFuture.get()
y CompletableFuture.join()
?
A continuación se muestra mi 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());
}
He intentado con ambos métodos pero no veo diferencia en el resultado.
java
java-8
completable-future
Nomeswaran
fuente
fuente
get()
requiere que detecte las excepciones marcadas. Debería notar la diferencia cuando cambie deget()
ajoin()
, ya que inmediatamente obtendrá un error del compilador que indica que niInterruptedException
ni seExecutionException
incluyen en eltry
bloque.join()
no se puede interrumpir.get
existe, porqueCompletableFuture
implementa laFuture
interfaz que lo exige.join()
lo más probable es que se haya introducido, para evitar la necesidad de detectar excepciones marcadas en expresiones lambda al combinar futuros. En todos los demás casos de uso, siéntase libre de usar lo que prefiera.Respuestas:
la única diferencia es cómo los métodos arrojan excepciones.
get()
se declara en laFuture
interfaz comoV get() throws InterruptedException, ExecutionException;
Las excepciones son excepciones marcadas, lo que significa que deben manejarse en su código. Como puede ver en su código, un generador de código automático en su IDE le preguntó si debía crear un bloque try-catch en su nombre.
try { CompletableFuture.allOf(fanoutRequestList).get() } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }
El
join()
método no arroja excepciones marcadas .public T join()
En su lugar, arroja CompletionException sin marcar. Por lo tanto, no necesita un bloque de prueba y captura y, en su lugar, puede aprovechar completamente el
exceptionally()
método cuando usa laList<String> process
función discutidaCompletableFuture<List<String>> cf = CompletableFuture .supplyAsync(this::process) .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException .thenAccept(this::processFurther);
Puede encontrar ambos
get()
y lajoin()
implementación aquífuente