Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly shutdown java ExecutorService

I have a simple java ExecutorService that runs some task objects (implements Callable).

ExecutorService exec = Executors.newSingleThreadExecutor();
List<CallableTask> tasks = new ArrayList<>();
// ... create some tasks
for (CallableTask task : tasks) {
 Future future = exec.submit(task);
 result = (String) future.get(timeout, TimeUnit.SECONDS);
 // TASKS load some classes and invoke their methods (they may create additional threads)
 // ... catch interruptions and timeouts
}
exec.shutdownNow();

After all tasks are finished (either DONE or TIMEOUT-ed), I try to shutdown the executor, but it wont stop: exec.isTerminated() = FALSE. I suspect that some tasks that are timeouted are not properly terminated.

And yes, I know that executor's shutdown is not guaranteing anything:

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via {@link Thread#interrupt}, so any task that fails to respond to interrupts may never terminate.

My question is, is there a way to ensure those (task) threads will terminate? The best solution I came up with, is to call the System.exit() at the end of my program, but that is plain silly.

like image 765
N10 Avatar asked Apr 15 '16 09:04

N10


People also ask

Should I shutdown ExecutorService?

Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

Does ExecutorService shutdown automatically?

Using shutdown() and awaitTermination​() In general, the ExecutorService will not be automatically destroyed when there is no task to process. It will stay alive and wait for new tasks to come.

How do I stop all threads in ExecutorService?

In the specific case of an ExecutorService , I would vote for supporting thread interruption rather than a flag. In many frameworks, the service will be terminated with shutdownNow() .

Can I reuse ExecutorService after shutdown?

After calling shutdown on a ExecutorService, no new Task will be accepted. This means you have to create a new ExecutorService for each round of tasks.


1 Answers

Recommended way from Oracle API documentation page of ExecutorService:

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }

If your pool is taking more time to shutdown, you can change

if (!pool.awaitTermination(60, TimeUnit.SECONDS))

to

while (!pool.awaitTermination(60, TimeUnit.SECONDS))

A brief summary of the shutdown related methods

shutdown():

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.

shutdownNow():

Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.

awaitTermination(long timeout, TimeUnit unit) throws InterruptedException:

Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.

like image 146
Ravindra babu Avatar answered Sep 19 '22 04:09

Ravindra babu