RandomQuestion
RandomQuestion

Reputation: 6998

Wait for task to finish before terminating in ScheduledThreadPoolExecutor

I have a Runnable implementation that does some work which might take some time and I am trying to schedule it using ScheduledThreadPoolExecutorwith scheduleAtFixedRate method. Now I want to ensure that shut down is graceful that means, Before terminating, task should be allowed to run completely. I have written following code for shutdown.

 public void shutDown() throws Exception {
    try {
        LOG.info("Gracefully shutting down executor");
        executor.shutdown();
        if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
            // cancels currently executing tasks.
            LOG.info("Executor is still alive. Forcing executor thread pool to shut down");
            executor.shutdownNow();

            // Wait a while for tasks to respond to being cancelled
            if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
                LOG.fatal("Executor thread pool did not terminate");
                throw new Exception("Unable to shut down executor thread pool forcefully");
            }
            LOG.info("Executor shut down.");
        }
    } catch (Exception e) {
        LOG.error("Exception shutting down executor", e);
        throw e;
    }
}

But problem with this is, I have to specify time to wait explicitly and I can not predict time taken by task in advance. Is there a way to make executor wait indefinitely until executing task finishes without having to mention time to wait? Or is there a better way to work on above scenario?

Thanks

Jitendra

Upvotes: 2

Views: 4826

Answers (3)

Tudor
Tudor

Reputation: 62469

Simplest solution is to "overprovision" so to speak. I suggest you use a huge timeout period that in no way can be exceeded by the time needed for a single task to execute, like:

// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

Upvotes: 1

dimitrisli
dimitrisli

Reputation: 21411

As it was noted in the comment executor.shutdown() is not forcing any tasks to exit but rather it prevents new ones from being accepted. Have a look in the javadoc.

Another advice is if you want to get hold of your tasks as soon as they complete, you can implement Callable<T> instead of a Runnable that it's of a generic type and returns a value of type T. Then you can wrap this Callable<T> into a FutureTask<V> and submit that to your ScheduledThreadPoolExecutor. You can then loop through your tasks as soon as they have completed their work and are available. So in short something like this (notice as soon as we are done loading the scheduler with tasks it's safe to shut it down meaning that we don't allow any further tasks to be submitted from then on):

ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(n);
Callable<Integer> myTask = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myTask);
schedulerExecutor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
schedulerExecutor.shutdown();

Upvotes: 0

Louis Wasserman
Louis Wasserman

Reputation: 198481

Use shutdown() to begin a graceful termination, and then use awaitTermination(long, TimeUnit) to wait for the executor service to finish shutting down.

Upvotes: 0

Related Questions