I am following the standard process that was recommended by oracle to shut down the executor services. here is the code that was recommended:
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();
}
}
I read through the descriptions for shutdown(), awaitTermination, and shutdownNow();
I understand that
shutdown() only stop submitting new threads.
awaitTermination waits for the running threads to be shutdown. Returns a value if one of completed execution, time out or current thread interrupted.
shutdownNow() use Thread.interrupt() to interrupt threads.
My question is, if I know for sure that my threads only use sleep which can be interrupted by Thread.interrupt(). Is there still a value to call awaitTermination like what oracle recommended?
I know that shutdownNow() might have a chance to not shutdown a thread, but why can't we go ahead and do something like this to force stop the threads then see if there are still threads not stoped?
pool.shutdown();
pool.shutdownNow();
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
The "standard process" just tries to handle the shutdown gracefully, the premise being not to interrupt the threads when it's not necessary.
First it stops accepting new task submissions and lets the ongoing tasks finish their work. It proceeds to forceful termination only when they don't finish within the grace period.
Related
I've this test code:
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println("run begins");
Thread.sleep(1000);
System.out.println("run ends");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
executor.awaitTermination(0L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("-----------");
I expected that, as the Runnable should sleep 1s and then ends, then executor await its termination and shutdown, finally, System.out.println("-----------"); is executed.
But the real output is:
-----------
run begins
run ends
The execution sequence doesn't make much sense to me. Seems the ExecutorService.awaitXXX and shutdown() doesn't block the main thread. The System.out.println("-----------"); was the first code line to print, and then the Runnable code.
Is this the designed behavior?
If yes, then my question is: if awaitXXXX method doesn't block the main thread, how does the main thread know when ExecutorService is done?
Seems the ExecutorService.awaitXXX and shutdown() doesn't block the
main thread
Method awaitTermination() does block the calling thread, but you've specified the timeout of 0 seconds. Quote from the javadoc:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
In case if you expected that awaitTermination() will interrupt submitted tasks, then your expectation is wrong, it wouldn't do that. This method only allows you to specify the period to wait and reports whether executor is done or not.
Returns:
true if this executor terminated and false if the timeout elapsed before termination
Method shutdown() also will not interrupt any tasks that are previously submitted:
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
If you wish to try to interrupt submitted tasks, use 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.
Note: usage of shutdown() is a preferred approach.
From the Javadocs of ExecutorService#awaitTermination:
Blocks until all tasks have completed execution after a shutdown request
This means that awaitTermination will only work after a shutdown request so you need to call shutdown() before awaitTermination().
Furthermore, as the other answer by #Alexander Ivanchenko mentions, setting a timeout of 0L will not wait for anything and awaitTermination indicates whether the thread terminated in time via a return value. The InterruptedException is thrown if your main thread is interrupted by another thread.
I'm unsuccessfully trying to cancel a thread submitted with this code
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Object> future = executor.submit(()-> {while(true) { System.out.println("Thread"); Thread.yield();} } );
Thread.sleep(3000);
future.cancel(true);
executor.shutdown();
but the thread stays running.
When sleep is used instead of yield, the thread does get cancelled. For example this does cancel the thread:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Object> future = executor.submit(()-> {while(true) { System.out.println("Thread"); Thread.sleep(1000);} } );
Thread.sleep(3000);
future.cancel(true);
executor.shutdown();
What's going on? Am I missing something in the documentation?
Your first task is NOT responsive to interruption. But the second task is responsive because Thread.sleep is a blocking method which is responsive to interruption. One way to solve the issue is by making your task responsive to interruption. Here's how it looks.
Future<?> future = executor.submit(() -> {
while (!Thread.currentThread().isInterrupted())
System.out.println("Thread");
});
Moreover Thread.yield is just a scheduler hint to yield its current use of a processor. This operation is platform dependent and should not be used in practice. Hence I have removed it from my answer.
If your intention is to stop all submitted tasks you could use
executor.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.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
As already mentioned in the comments section of the question, it is the difference between .sleep(1000) and .yield() behaviour for interrupt calls
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.
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.
Do you have control of those tasks ? i.e. are you creating those yourself ? I suspect somewhere in those a thread interrupt is being ignored e.g.
try {
....
}
catch {InterruptedException e) {
// do nothing
}
When an InterruptedException is thrown, the interrupt flag on the thread needs to be reset, otherwise the thread will not exit. See here for more info.
Unfortunately you may be using a library that doesn't obey this, in which case you can't easily circumvent this. In that case one heavyweight option is to fork off a sub process to perform the job of the Callable, and that will clear up all resources upon process exit. Heavyweight and possibly non-trivial, but reliable.
I an using ThreadPoolExecutor in java to excute multi threads, and I have to do something after threads finish, and have to wait.
So I want to ask what is the best way to do that?
Is that right I do in the way?
threadPool.shutdown();
boolean loop = true;
Integer x = threadPool.getPoolSize();
while (threadPool.getPoolSize() != 0) {
}
Shutdown will initiate an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
executor.shutdown();
System.out.println("All tasks submitted...No new tasks will be admitted");
However, I would strongly recommend using awaitTermination as this will allow current thread to block until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
try {
executor.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
EDIT:
The runState provides the main lifecyle control, taking on values:
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
* STOP: Don't accept new tasks, don't process queued tasks,
* and interrupt in-progress tasks
* TIDYING: All tasks have terminated, workerCount is zero,
* the thread transitioning to state TIDYING
* will run the terminated() hook method
* TERMINATED: terminated() has completed
The numerical order among these values matters, to allow ordered comparisons. The runState monotonically increases over time, but need not hit each state.
The transitions are:
RUNNING -> SHUTDOWN
On invocation of shutdown(), perhaps implicitly in finalize()
(RUNNING or SHUTDOWN) -> STOP
On invocation of shutdownNow()
SHUTDOWN -> TIDYING
When both queue and pool are empty
STOP -> TIDYING
When pool is empty
TIDYING -> TERMINATED
When the terminated() hook method has completed. Threads waiting in awaitTermination() will return when the state reaches TERMINATED.
Detecting the transition from SHUTDOWN to TIDYING is less straightforward than you'd like because the queue may become empty after non-empty and vice versa during SHUTDOWN state, but we can only terminate if, after seeing that it is empty, we see that workerCount is 0.
Going back to your question, when you call getPoolSize() it checks the state of the threadpool when it is in TIDYING state. Hence, I think the correct check should be against TERMINATED state. Although, the results are the same if you have not implemented terminated() method.
If you want to wait gracefully, refer to solutions in below question:
How to wait for completion of multiple tasks in Java?
If you are not using any of them ( invokeAll, CountDownLatch) and submit the jobs and waiting for executor to finish the tasks, refer to
How to forcefully shutdown java ExecutorService
Basic code snippet in this case:
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();
}
I want to know the basic difference between shutdown() and shutdownNow() for shutting down the Executor Service?
As far as I understood:
shutdown() should be used for graceful shutdown which means all tasks that were running and queued for processing but not started should be allowed to complete
shutdownNow() does an abrupt shut down meaning that some unfinished tasks are cancelled and unstarted tasks are also cancelled. Is there anything else which is implicit/explicit that I am missing?
P.S: I found another question on How to shutdown an executor service related to this but not exactly what I want to know.
In summary, you can think of it that way:
shutdown() will just tell the executor service that it can't accept new tasks, but the already submitted tasks continue to run
shutdownNow() will do the same AND will try to cancel the already submitted tasks by interrupting the relevant threads. Note that if your tasks ignore the interruption, shutdownNow will behave exactly the same way as shutdown.
You can try the example below and replace shutdown by shutdownNow to better understand the different paths of execution:
with shutdown, the output is Still waiting after 100ms: calling System.exit(0)... because the running task is not interrupted and continues to run.
with shutdownNow, the output is interrupted and Exiting normally... because the running task is interrupted, catches the interruption and then stops what it is doing (breaks the while loop).
with shutdownNow, if you comment out the lines within the while loop, you will get Still waiting after 100ms: calling System.exit(0)... because the interruption is not handled by the running task any longer.
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
#Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("interrupted");
break;
}
}
}
});
executor.shutdown();
if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
System.out.println("Still waiting after 100ms: calling System.exit(0)...");
System.exit(0);
}
System.out.println("Exiting normally...");
}
shutdown():
To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.
shutdownNow():
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.
From the javadocs:
void shutdown
Initiates an orderly shutdown in which previously submitted tasks are
executed, but no new tasks will be accepted.
List<Runnable> 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.
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.
Returns: list of tasks that never commenced execution