akila
akila

Reputation: 687

ExecutorService shutdownNow is not shutting down the JVM

Am learning about ExecutorService introduced in Java 1.5

The following example seems to defy expected behaviour :

public static void main(String[] args) throws InterruptedException,
ExecutionException,TimeoutException  {
    
    Callable<String> task = () -> {
        int counter = 0;
        while(true) {
            //infinite loop will never exit
            if(counter == 7) {
                break;
            }
        }
        return "abc";
    };
    
    ExecutorService service = Executors.newSingleThreadExecutor();          
    try {
    Future<String> future = service.submit(task);
    
        System.out.println("result = " + future.get(10000,TimeUnit.MILLISECONDS));
    }finally {
        System.out.println("<<<< finally >>>>");
        service.shutdownNow();
    }
    
    
    
}

Looking at java docs for this method:

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

This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

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

So ideally what I was expecting was that after specified timeout I would get a Timeout exception and then the ExecutorService would shutdown forcefully but that does not happen.

Looked at the java doc - and it does seem to indicate that there is no guarantee that it would shutdown.

If its not guaranteed then should it be avoided ?

Upvotes: 0

Views: 788

Answers (1)

Stephen C
Stephen C

Reputation: 718678

Looked at the java doc - and it does seem to indicate that there is no guarantee that it would shutdown.

Correct.

If its not guaranteed then should it be avoided ?

No.

What you should actually be doing is to use ExecutorService in a way that avoids or works around the limitations; e.g.

  • Implement any tasks that may be long running and that should be killable so that they do handle interrupts correctly. If you do that correctly, then your ExecutorService will terminate.

  • Don't depend on the ExecutorService actually shutting down. For example, you could arrange that when the application needs to shutdown, it does the following:

    1. it calls shutdownNow()
    2. it calls awaitTermination(...) with an appropriate timeout
    3. if the ExecutorService doesn't terminate then it calls System.exit(...) to terminate the application.
  • Configure your ExecutorService to create the worker threads as daemon threads; see Turning an ExecutorService to daemon in Java.

    A daemon thread won't prevent the JVM from exiting. But note that you need to be careful. If all non-daemon threads have finished, the JVM will pull the plug without interrupting any tasks that the ExecutorService is currently running.

Upvotes: 2

Related Questions