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:
Thread.currentThread().isInterrupted()
Since I am in a situation where:
ExecutorService.shutdownNow()
, but is not shut down, that is, ExecutorService.awaitTermination(long, TimeUnit)
never returns true
BlockingQueue.take()
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:
ExecutorService.shutdownNow()
is not thread safe?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.
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.
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With