Выполнить whenComplete из CompletableFuture в исходном потоке

Как я могу запустить whenComplete из CompletableFuture в исходном потоке, в котором был создан CompletableFuture?

    // main thread
    CompletableFuture
            .supplyAsync(() -> {
                // some logic here
                return null;
            }, testExecutorService);
            .whenComplete(new BiConsumer<Void, Throwable>() {
                @Override
                public void accept(Void aVoid, Throwable throwable) {
                // run this in the "main" thread 
                }
            });

Просто интересно: когда вы проверяете потоки, которые здесь используются, оба находятся в исполнителе тестов? Я бы предположил, что whenComplete() уже делает то, что вы ищете?

GhostCat 03.02.2019 21:31

Проще говоря: вы этого не сделаете, потому что вы потеряете преимущества асинхронных вычислений, если дождетесь завершения задачи. Более сложный: в случаях пользовательского интерфейса, таких как Swing или JavaFX, вы можете запланировать выполнение задачи после завершения (SwingUtilities.invokeLater() или Platform.runLater()).

tobain 03.02.2019 21:32

@GhostCat Нет, это не так. whenComplete() будет запущен в любом из асинхронных потоков, но не в исходном.

tobain 03.02.2019 21:35

тогда какая польза от @Async, вы можете выполнить эту задачу в основном потоке, который создает асинхронный поток

Deadpool 03.02.2019 21:39
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
1 465
1

Ответы 1

Расширенный пример для JavaFx:

    button.setOnClick((evt) -> {
        // the handler of the click event is called by the GUI-Thread
        button.setEnabled(false);
        CompletableFuture.supplyAsync(() -> {
            // some logic here (runs outside of GUI-Thread)
            return something;
        }, testExecutorService);
        .whenComplete((Object result, Throwable ex) -> {
            // this part also runs outside the GUI-Thread
            if (exception != null) {
                // something went wrong, handle the exception 
                Platform.runLater(() -> {
                    // ensure we update the GUI only on the GUI-Thread
                    label.setText(ex.getMessage());
                });
            } else {
                // job finished successfull, lets use the result
                Platform.runLater(() -> {
                    label.setText("Done");
                });
            }
            Platform.runLater(() -> {
                button.setEnabled(true); // lets try again if needed
            });
        });
    });

Это не лучший код, который вы могли бы написать в этой ситуации, но он должен донести суть.

благодаря. Что скрывается за Platform.runLater? Я не использую java fx, поэтому я бы предпочел пример java se/ee

Sergei Ledvanov 04.02.2019 10:03

Поток пользовательского интерфейса JavaFX работает в бесконечном цикле, подобном следующему: он спит и ждет события. Если он получает один, то он решает, что делать. Если событие предназначено для компонента пользовательского интерфейса, то он передает это событие компоненту (компонентам) и запускает обработчики событий этого компонента (компонентов). Метод runLater() запускает специальное событие, содержащее java.lang.Runnable, которое затем запускается в этом потоке пользовательского интерфейса. Он передает задание потоку пользовательского интерфейса, который должен быть запущен как можно скорее, но после выполнения событий пользовательского интерфейса. После этого поток пользовательского интерфейса выполняет перерисовку на экране и ожидает следующего события (событий).

tobain 06.02.2019 01:04

Другие вопросы по теме