У меня очень странная проблема с CompletableFuture.
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
final static ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
final CompletableFuture withoutExecutor = doSomethingOne(i);
// final CompletableFuture withExecutor = doSomethingTwo(i);
}
}
private static CompletableFuture doSomethingOne(final int i) {
return CompletableFuture.runAsync(() -> {
System.out.println("Without Executor " + i);
});
}
private static CompletableFuture doSomethingTwo(final int i) {
return CompletableFuture.runAsync(() -> {
System.out.println("With Executor " + i);
}, executor);
}
}
Когда main
выполняется, он ничего не печатает (withoutExecutor
CompletableFuture даже не выполняется). Но когда я раскомментирую withExecutor
, оба CompletableFuture работают как положено. Что мне не хватает?
У меня похожая проблема в моем личном проекте, но общая идея та же. В настоящее время я использую исполнитель с моими CompletableFuture в проекте, и они работают только в течение определенного периода времени, а затем полностью перестают работать (даже отладчик не достигает точки останова в CompletableFuture). Мне нужна асинхронная фоновая задача, ожидание не вариант, так как CompletableFuture запускается через REST API в моем проекте, и я должен вернуть результат сохранения истории как можно скорее.
Дубликат относится к коду в вашем вопросе. Я не уверен, решит ли это проблему в вашем реальном проекте. Подскажите так или иначе, пожалуйста.
Попробуйте этот код
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
public class Main {
private static final ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Consumer<Integer> consumer = result -> System.out.println("Result: " + result);
doSomething(i)
.thenAcceptAsync(consumer, executor);
}
System.out.println("Main thread is not blocked");
}
private static CompletableFuture<Integer> doSomething(final int i) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2500);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
return i * 3;
}, executor);
}
}
Спасибо, это работает. Но проблема в том, что это блокирующий механизм из-за join(). Мне нужно что-то вроде асинхронной фоновой задачи
@HashamRasheed Если цель состоит в том, чтобы иметь асинхронную фоновую задачу, вы можете изменить код, чтобы использовать функцию обратного вызова для обработки результатов после завершения CompletableFuture. Позвольте мне изменить свой ответ, чтобы продемонстрировать вам.
@HashamRasheed попробуйте обновленный код, пожалуйста :-)
@HashamRasheed все хорошо? Дайте мне знать, если я могу вам помочь. :-)
@HashamRasheed Добро пожаловать! Рад помочь вам! :) Дайте мне знать, если у вас возникнут другие проблемы, пожалуйста.
Предположения, но, возможно, связанные с окончанием
main
(так что вся программа заканчивается) до того, какCompleteFuture
успеет запуститься. Это также может зависеть от того, создает ли пул потоков рабочих как поток демона или не-демона.