Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel ScheduledFuture task from another task and end gracefully?

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?

like image 441
voho Avatar asked Sep 23 '15 13:09

voho


People also ask

Can a Callable task can be cancelled?

A Callable task can be canceled.

How do I stop scheduled executor service?

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.

How to stop executor Java?

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.


1 Answers

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.

like image 105
Tunaki Avatar answered Sep 30 '22 14:09

Tunaki