Jaka jest różnica między CompletableFuture.get()
i CompletableFuture.join()
?
Poniżej znajduje się mój kod:
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());
}
Próbowałem z obiema metodami, ale nie widzę różnicy w wyniku.
java
java-8
completable-future
Nomeswaran
źródło
źródło
get()
wymaga wyłapania zaznaczonych wyjątków. Powinieneś zauważyć różnicę po zmianie zget()
najoin()
, ponieważ natychmiast otrzymasz błąd kompilatora mówiący, że aniInterruptedException
nieExecutionException
są wyrzucane wtry
bloku.join()
nie można przerwać.get
istnieje, ponieważCompletableFuture
implementujeFuture
interfejs, który to narzuca.join()
najprawdopodobniej została wprowadzona, aby uniknąć konieczności wyłapywania sprawdzonych wyjątków w wyrażeniach lambda podczas łączenia futures. We wszystkich innych przypadkach możesz swobodnie używać tego, co wolisz.Odpowiedzi:
jedyną różnicą jest sposób, w jaki metody zgłaszają wyjątki.
get()
jest zadeklarowana wFuture
interfejsie jakoV get() throws InterruptedException, ExecutionException;
Wyjątki są wyjątkami zaznaczonymi, co oznacza, że muszą być obsługiwane w kodzie. Jak widać w Twoim kodzie, automatyczny generator kodu w Twoim IDE zapytał, czy utworzyć blok try-catch w Twoim imieniu.
try { CompletableFuture.allOf(fanoutRequestList).get() } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); }
join()
Metoda nie rzucać sprawdzonych wyjątków.public T join()
Zamiast tego zgłasza niesprawdzony CompletionException. Więc nie potrzebujesz bloku try-catch, a zamiast tego możesz w pełni wykorzystać
exceptionally()
metodę podczas korzystania zList<String> process
funkcji rozproszonejCompletableFuture<List<String>> cf = CompletableFuture .supplyAsync(this::process) .exceptionally(this::getFallbackListOfStrings) // Here you can catch e.g. {@code join}'s CompletionException .thenAccept(this::processFurther);
Możesz znaleźć oba
get()
ijoin()
implementację tutajźródło