Как я могу запустить 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
}
});
Проще говоря: вы этого не сделаете, потому что вы потеряете преимущества асинхронных вычислений, если дождетесь завершения задачи. Более сложный: в случаях пользовательского интерфейса, таких как Swing или JavaFX, вы можете запланировать выполнение задачи после завершения (SwingUtilities.invokeLater() или Platform.runLater()).
@GhostCat Нет, это не так. whenComplete() будет запущен в любом из асинхронных потоков, но не в исходном.
тогда какая польза от @Async, вы можете выполнить эту задачу в основном потоке, который создает асинхронный поток




Расширенный пример для 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
Поток пользовательского интерфейса JavaFX работает в бесконечном цикле, подобном следующему: он спит и ждет события. Если он получает один, то он решает, что делать. Если событие предназначено для компонента пользовательского интерфейса, то он передает это событие компоненту (компонентам) и запускает обработчики событий этого компонента (компонентов). Метод runLater() запускает специальное событие, содержащее java.lang.Runnable, которое затем запускается в этом потоке пользовательского интерфейса. Он передает задание потоку пользовательского интерфейса, который должен быть запущен как можно скорее, но после выполнения событий пользовательского интерфейса. После этого поток пользовательского интерфейса выполняет перерисовку на экране и ожидает следующего события (событий).
Просто интересно: когда вы проверяете потоки, которые здесь используются, оба находятся в исполнителе тестов? Я бы предположил, что whenComplete() уже делает то, что вы ищете?