Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExecutorService.shutdownNow() does not shut down threads

I am running a highly concurrent Java program. While many threads are submitting tasks to an executor service, at a certain point the main thread invokes ExecutorService.shutdownNow().

After this action, I would expect that:

  1. No additional task would be accepted by the executor service
  2. The executor service's queue is clear
  3. The remaining running workers are interrupted, that is, at a certain point they shut down if they correctly manage the InterruptedException and / or explicitly check Thread.currentThread().isInterrupted()

Since I am in a situation where:

  1. The executor service is "shutting down" due to an ExecutorService.shutdownNow(), but is not shut down, that is, ExecutorService.awaitTermination(long, TimeUnit) never returns true
  2. There are some pending threads managed by my executor service waiting on a BlockingQueue.take()
  3. If I invoke again ExecutorService.shutdownNow(), the pending threads die by InterruptedException on BlockingQueue.take()

I suppose that the interruption was received by those threads before invoking BlockingQueue.take() and the InterruptedException was ignored.

I was also wondering if the ExecutorService.shutdownNow() is thread safe, that is, it works correctly even if the thread pool is receiving many submissions.

All in all, I would have two questions:

  1. Is there any alternative scenario that would explain my situation?
  2. Is it possible that ExecutorService.shutdownNow() is not thread safe?
like image 765
Mirko Avatar asked Jun 20 '14 12:06

Mirko


People also ask

What happens if ExecutorService is not shutdown?

If it's not shut down yet, the shutdown method is invoked on the service. Finally, we wait for the termination of the service for one second using the awaitTermination method.

How do I stop all threads in ExecutorService?

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.

How do you shut down an ExecutorService?

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. It is up to the developer to decide what to do with these tasks.

How is thread lifecycle maintained using ExecutorService framework?

The executor service creates and maintains a reusable pool of threads for executing submitted tasks. The service also manages a queue, which is used when there are more tasks than the number of threads in the pool and there is a need to queue up tasks until there is a free thread available to execute the task.


1 Answers

Is there any alternative scenario that would explain my situation?

There must be something in your thread code that is resetting the interrupted flag or swallowing an InterruptedException thrown by another method call.

If the interrupted flag is set before the execution reaches the BlockingQueue.take() method, that method will still throw an InterruptedException and abort. This is demonstrated in the following code, which exits immediately and prints "Interrupted!":

final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);

Thread t = new Thread() {
    @Override
    public void run() {
        Thread.currentThread().interrupt();

        try {
            queue.take();
        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        }
    };
};
t.start();

Is it possible that ExecutorService.shutdownNow() is not thread safe?

See, for instance: Is ThreadPoolExecutor thread safe?. According to that answer, all standard implementations of ExecutorService are thread-safe (even if the Javadocs are not explicit on that subject).

like image 94
Duncan Jones Avatar answered Oct 12 '22 13:10

Duncan Jones