Можно ли запланировать CompletableFuture? - PullRequest
1 голос
/ 05 ноября 2019

Есть ли способ запланировать CompletableFuture в Java? Я хотел запланировать выполнение задачи с некоторой задержкой и связать ее с другими операциями, которые будут выполняться асинхронно после ее завершения. До сих пор я не нашел никакого способа сделать это.

Для добрых старых фьючерсов у нас есть, например, ScheduledExecutorService, где мы можем запланировать выполнение задачи с некоторой задержкой, например:

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Future<String> future = scheduledExecutorService.schedule(() -> "someValue", 10, TimeUnit.SECONDS);

Есть ли аналогичный способ для CompletableFutures?

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019

Как уже говорилось , в Java 9 есть поддержка.

Но создать подобную функцию под Java 8 несложно;Вы уже назвали необходимые элементы:

// prefer this constructor with zero core threads for a shared pool,
// to avoid blocking JVM exit
static final ScheduledExecutorService SCHEDULER = new ScheduledThreadPoolExecutor(0);
static Executor delayedExecutor(long delay, TimeUnit unit)
{
  return delayedExecutor(delay, unit, ForkJoinPool.commonPool());
}
static Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
{
  return r -> SCHEDULER.schedule(r, delay, unit);
}

, которые можно использовать аналогично функции Java 9: ​​

Executor afterTenSecs = delayedExecutor(10L, TimeUnit.SECONDS);
CompletableFuture<String> future 
  = CompletableFuture.supplyAsync(() -> "someValue", afterTenSecs);

future.thenAccept(System.out::println).join();

Необходимо позаботиться о том, чтобы потоки общего запланированного исполнителя не позволялиJVM от прекращения. Альтернативой нулевому размеру основного пула является использование потоков демона:

static final ScheduledExecutorService SCHEDULER
  = Executors.newSingleThreadScheduledExecutor(r -> {
    Thread t = new Thread(r);
    t.setDaemon(true);
    return t;
  });
2 голосов
/ 05 ноября 2019

Если вы используете Java 9+, тогда CompletableFuture#delayedExecutor(long,TimeUnit) может соответствовать вашим потребностям:

Возвращает нового исполнителя, который отправляет задание исполнителю по умолчанию после указанногозадержка (или нет задержки, если не положительный). Каждая задержка начинается после вызова метода execute возвращенного исполнителя.

Executor delayed = CompletableFuture.delayedExecutor(10L, TimeUnit.SECONDS);
CompletableFuture.supplyAsync(() -> "someValue", delayed)
    .thenAccept(System.out::println)
    .join();

Также имеется перегрузка , где вы можете указать Executor для использования вместо"исполнитель по умолчанию".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...