How to properly shutdown java ExecutorService
executorservice, java, multithreading, shutdown
Solution
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.
Problem
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.