Is it possible to schedule a CompletableFuture?
As said, there is support in Java 9.
But it’s not hard to create a similar feature under Java 8; you already named the necessary elements:
// 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(() -> executor.execute(r), delay, unit);
}
which can be used similarly to the Java 9 feature:
Executor afterTenSecs = delayedExecutor(10L, TimeUnit.SECONDS);
CompletableFuture<String> future
= CompletableFuture.supplyAsync(() -> "someValue", afterTenSecs);
future.thenAccept(System.out::println).join();
Care must be taken to avoid that the shared scheduled executor’s threads prevent the JVM from terminating. The alternative to a zero core pool size is to use daemon threads:
static final ScheduledExecutorService SCHEDULER
= Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
If you're using Java 9+ then CompletableFuture#delayedExecutor(long,TimeUnit)
may fit your needs:
Returns a new Executor that submits a task to the default executor after the given delay (or no delay if non-positive). Each delay commences upon invocation of the returned executor's
execute
method.
Executor delayed = CompletableFuture.delayedExecutor(10L, TimeUnit.SECONDS);
CompletableFuture.supplyAsync(() -> "someValue", delayed)
.thenAccept(System.out::println)
.join();
There's also an overload where you can specify the Executor
to use in place of the "default executor".