I am playing with ScheduledExecutorService
. What I want to do is to start a simple ticker (one tick per second) and schedule another task later (after five seconds) which cancels the first one. And then block the main thread until everything finishes, which should be after both tasks finish (+- five seconds).
This is my code:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Runnable tickTask = () -> System.out.println("Tick");
ScheduledFuture<?> scheduledTickTask = executor.scheduleAtFixedRate(tickTask, 0, 1, TimeUnit.SECONDS);
Runnable cancelTask = () -> scheduledTickTask.cancel(true);
executor.schedule(cancelTask, 5, TimeUnit.SECONDS);
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
The problem which suprises me is that it BLOCKS as if there were still some running tasks. Why? The cancelTask
should end immediately and the scheduledTickTask
was just cancelled, so what is the problem?
A Callable task can be canceled.
To properly shut down an ExecutorService, we have the shutdown() and shutdownNow() APIs. This method returns a list of tasks that are waiting to be processed.
Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks.
As per the Javadoc of ExecutorService.awaitTermination
(emphasis mine):
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
That means you need to call shutdown
first, like this:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Runnable tickTask = () -> System.out.println("Tick");
ScheduledFuture<?> scheduledTickTask = executor.scheduleAtFixedRate(tickTask, 0, 1, TimeUnit.SECONDS);
Runnable cancelTask = () -> {
scheduledTickTask.cancel(true);
executor.shutdown();
};
executor.schedule(cancelTask, 5, TimeUnit.SECONDS);
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
In your case, the timeout will never happen because you practically set it to "infinity" and the current thread is not interrupted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With