8

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?
Cœur
  • 37,241
  • 25
  • 195
  • 267
Mirko
  • 81
  • 1
  • 2
  • 2
    What are your threads doing prior to calling `BlockingQueue.take()`? Is it possible they do something which catches/ignores `InterruptedException` or otherwise clears the interrupt status of the Thread? An example of this is Oracle's UCP connection pooling which will clear the interrupt status if validating on borrow is enabled (Bug 16298836). – Brett Okken Jun 20 '14 at 13:01
  • This thread might be helpful http://stackoverflow.com/questions/11520189/difference-between-shutdown-and-shutdownnow-of-executor-service – Ivan Jun 20 '14 at 13:35

1 Answers1

4

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).

Community
  • 1
  • 1
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254