завершене майбутнє приєднання проти get


93

У чому різниця між CompletableFuture.get()і CompletableFuture.join()?

Нижче мій код:

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

Я пробував обидва методи, але не бачу різниці в результаті.


10
get()вимагає, щоб ви ловили перевірені винятки. Ви повинні помітити різницю, коли переходите з get()на join(), оскільки ви одразу отримаєте помилку компілятора, сказавши, що ні, InterruptedExceptionні ExecutionExceptionкидаються в tryблок.
Holger

5
@ holi-java: join()не можна перервати.
Holger

@Holger так, сер. Я виявив, що не можу перервати завдання.
holi-java

9
Добре getіснує, оскільки CompletableFutureреалізує Futureінтерфейс, який це вимагає. join()швидше за все, було введено, щоб уникнути необхідності ловити перевірені винятки в лямбда-виразах при комбінуванні ф’ючерсів. У всіх інших випадках використання сміливо використовуйте те, що вам більше подобається.
Holger

1
Чи справді має сенс використовувати join або get як обидва блоки на потоці. Чи не можемо ми замість цього зробити цю асинхронність, використовуючи інші методи композиції, щоб створити ланцюжок асинхронних функцій. Звичайно, це залежить від функціональності. Але у випадку, наприклад, метод служби навесні, викликаний методом контролера, що повертає повне майбутнє, має більше сенсу взагалі не викликати метод get або приєднуватися до служби. Це робить?
Shailesh Vaishampayan

Відповіді:


107

різниця лише в тому, як методи кидають винятки. get()оголошується в Futureінтерфейсі як

V get() throws InterruptedException, ExecutionException;

Винятки - це перевірені винятки, що означає, що їх потрібно обробляти у коді. Як ви можете бачити у своєму коді, автоматичний генератор коду у вашій IDE запитав, чи потрібно створювати блок try-catch від вашого імені.

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

join()Метод не викидає відмічені виключення.

public T join()

Натомість він викидає неперевірений CompletionException. Так що вам не потрібен примірка зловити блок і замість цього ви можете в повній мірі використовувати exceptionally()метод при використанні disscused List<String> processфункції

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

Ви можете знайти як get()і join()здійснення тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.