Я пытаюсь использовать функции Java 8 CompletableFuture, в которых говорится, что это дает возможность работать асинхронно. Но для того, чтобы выполнить то, что в «будущем», необходимо вызвать метод future.get(). Это блокирует основной поток. поскольку он ждет 30 секунд сна перед выполнением строки после future.get()
Есть ли способ добиться этого? Выполните неблокирующий способ выполнения я пытаюсь распечатать
"I'll run in the main thread."
до
"I'll run in a separate thread than the main thread."
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
// Simulate a long-running Job
try {
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("I'll run in a separate thread than the main thread.");
}
});
future.get();
System.out.println("I'll run in the main thread.");
}
@Lino, так что есть альтернатива?
Вы можете просто переместить основной оператор печати доfuture.get(), но это кажется упрощенным, поэтому я не совсем уверен, в чем ваша проблема -> почему вам нужно, чтобы основное действие предшествовало действию потока
нет смысла перемещать утверждение. фактический сценарий заключается в выполнении таймера параллельно основному потоку. но метод должен продолжать выполняться без блокировки на будущее. фактический сценарий - это вызов Rest, который попадает в метод конечной точки. но параллельное выполнение не должно блокировать метод конечной точки, возвращающий ответ
CompletableFuture.runAsync( уже запускает другой ваш поток. Вызов future.get() — это просто способ дождаться окончания выполнения этого потока и получить его результат, прежде чем вы продолжите выполнение вызова в потоке.
Спецификации говорят, что CompletableFuture предназначен для неблокирующего запуска задач. но мне было интересно, как мы это делаем.
@xtratic, что такое я не хочу ждать, пока этот поток завершит работу. Я пробовал без future.get(). хотя тогда основной поток не был заблокирован, он все равно не печатал то, что находится в потоке.
CompletableFutureявляется работает без блокировки
@ShenaliSilva, когда вы удаляете вызов get(), основной поток не блокируется, и, поскольку в вашем упрощенном примере больше ничего нет, он завершится. JVM завершит работу, когда останутся только потоки Daemon, поэтому вы можете увидеть или не увидеть сообщение печати, в зависимости от непредсказуемого времени. Это не проблема реальных приложений. Но когда вы в упрощенном примере должны распечатать сообщение в фоновом потоке, вы должны подождать, прежде чем завершить его.




CompletableFuture.runAsync(Runnable) уже запускает другой ваш поток. Вызов future.get() — это просто способ дождаться окончания выполнения этого потока и получить его результат, прежде чем вы продолжите выполнение вызова в потоке.
Когда вы запускаете поток и get сразу, ничего не делая между ними (как вы это делаете), тогда нет смысла запускать поток.
фактический сценарий заключается в выполнении таймера параллельно основному потоку. но метод должен продолжать выполняться без блокировки на будущее. фактический сценарий - это вызов Rest, который попадает в метод конечной точки. но параллельное выполнение не должно блокировать метод конечной точки, возвращающий ответ
То, чего вы пытаетесь достичь, не будет таким тривиальным, если я правильно понял. У вас есть входящий вызов, и вы хотите обработать этот вызов без вмешательства, и наряду с этим потоком вы хотите запустить отдельный процесс, независимый от основного процесса. (Поправьте меня, если я неправильно понял)
Я бы решил это с помощью очереди. Вы основной поток отправляете что-то в очередь и выполняете то, что ему нужно для выполнения. Затем есть отдельные потребители, прослушивающие очередь, которые будут выполнять другой процесс, не влияя на основной поток.
future.get()блокирует основной поток, поэтому оператор печати потока всегда будет выполняться перед печатью основного потока.