Does java ExecutorService.awaitTermination() block the main thread and wait? - java

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.

Related

How to properly shutdown java ExecutorService

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.

what is the best way to wait ThreadPoolExecutor finish thread in java?

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();
}

ExecutorService awaitTermination shutdown signal in the Runnable instance

I've a few questions around ExecutorService and the shutdown process.
My use case:
I use an ExecutorService to spawn a fixed number of threads whose run method look like this:
while (true) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
These threads run infinitely, polling for messages.
What am I trying to do?
I am polling an SQS queue for messages and processing them.
Obviously, in my case, the ExecutorService's shutdown method would not work. When shutdownNow() is called, all my threads are shutdown unceremoniously. I hate it!
Is there a way to invoke awaitTermination and verify, in my Runnable instance(in a finally block?), if shutdown has been initiated and trigger the same for the current thread?
UPDATE: I've refactored my code to perform polling and then spawning threads to process them. Thus, the Runnable instance's run method need not be an endless loop. And awaiTermination will lead to a definite closure of the threads. And to be sure, I've triggered shutdownNow after awaitTermination.
I think what you are doing is conceptually wrong.
awaitTermination is meant to wait for all threads to finish naturally and then stop the executor. When submitting a Runnable, it shouldn't have an idea of the context of it's execution, so, coupling your runnable to your executor is not a good idea IMHO.
Maybe you should look into the Future class and move your Runnable implementation there. Then you will be forced to implement a cancel(boolean) method which you might find useful.
What is exactly your use case? Maybe if you explain it, the community can point out a better suited implementation.
For infinitely running Runnables I rely on catching an InterruptedException, which will typically be thrown from my calling shutdownNow() or occasionally from calling Future#cancel(true)
while(!Thread.interrupted()) {
try {
} catch(InterruptedException e) {
break;
} catch(Throwable e) {
// Keeping the thread alive despite exception
}
}
// Thread was interrupted via shutdownNow(), cleanup resources
If I need to distinguish between a resumable interrupt and a shutdown interrupt then I share an AtomicBoolean doShutdown among my Runnables that is initialized to false and set to true if I want an InterruptedException to terminate the thread.
You have to check the interrupt status of the thread you are running in (see tutorial on interrupts here: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html). Your code should be:
while (!Thread.currentThread().isInterrupted()) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
Note however that you do have to handle interrupts correctly in code called from your runnable. If there is anything like the following:
try {
// do something
} catch(InterruptedException e) {
// ignore
}
then this won't work. The correct way to handle InterruptedException is to call Thread.currentThread().interrupt();.
You should not call shutdownNow() But you should only call shutdown and use awaitTermination to wait for some time.
So shutdown would be something like this
Declare a volatile variable
private volatile stopThread = false;
On shutdown you call
this.stopThread = true;
executor.shutdown();
executor.awaitTermination(..
executor.shutdownNow() // in case termination takes too long
And in the thread you check for the stopThread variable. You cannot use isInterrupted here because we are not interrupting the thread. we are just waiting for the thread to exit based on this condition
if(stopThread){
// calling off all the operations and returning
}
I have written an article about shuting down the executorservice properly
http://programtalk.com/java/executorservice-not-shutting-down/
I hope this will help you.

Difference between shutdown and shutdownNow of Executor Service

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

Java Thread Pools/Executor Service and wait()s - what happens to the threads & task queue?

I've looked around but haven't found an answer so I wanted to confirm this for certain.
Say I have a fixed size thread pool - ExecutorService pool = Executors.newFixedThreadPool(5);
And I have some code:
pool.execute(new Runnable(){
try{
Object waitForMe = doSomethingAndGetObjectToWaitFor();
waitForMe.wait();
doSomethingElse();
}catch(Exception e){ throw new RunTimeException(e) }
});
Lets assume that the above code is called a few 100 times. There are only 5 threads in the pool (so only 5 of the above statements should be live at one point). Also assume that the wait() is on an object doing some I/O calls to a thrid party and waiting for a callback when the operation is complete so it will naturally take a while to complete.
Now my question is what is the behavior when one of these tasks reaches a wait(), does the task go to sleep and then the thread from the thread pool takes another task off queue and starts running it?
If the task that is waiting goes to sleep what happens when it gets a notify() and wakes up? Does the thread go back into the queue (at the front or back) for the thread pool and wait until one of the 5 threads can continue to execute it (i.e. call doSomethingelse())? Or does the thread that was executing it also go to sleep i.e. one of the 5 executor threads sits waiting with the task (this is what I'm assuming)? Or does the executor thread pick up another task and simply get interrupted when the first task returns from the wait()?
wait() is a blocking operation:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll()
This means that the thread in the pool will wait, but from outside it just looks like the current task takes so much time to complete. This also means that if 5 tasks are executed and they all wait(), the Executor cannot handle remaining tasks that, ekhem, wait in the queue.
True, the executor thread itself goes to sleep allowing other threads to switch and consume CPU (so you can have hundreds of threads waiting at the same time and your system is still responsive) but still the thread is "unusable" and blocked.
Another interesting feature is interrupting - if the thread waits for something or sleeps you can interrupt it. Note that both wait() and Thread.sleep() declare InterruptedException. With ExecutorService you can take advantage of this by simply calling: future.cancel() (future is the object you got in return when submit task to ExecutorService).
Finally I think you should redesign your solution. Instead of actively waiting for an external system to finish, provide an API with callbacks:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
This way the external system's API will simply notify you when the results are ready and you won't have to wait and block ExecutorService. Finally, if doSomethingElse() takes a lot of time, you might even decide to schedule it as well rather than using external third-party I/O thread:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItIsDone(new Callback() {
public void done() {
pool.submit(new Callbale<Void>() {
public Void call() {
doSomethingElse();
}
}
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
UPDATE: you are asking what to do about timeouts? Here is my idea:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
public void timeout() {
//opps!
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
I guess you can implement timeout on the third-party side and if timeout occurs there, simply call timeout() method.
The wait() cannot know anything about the tread pool. And the thread pool cannot know anything about the wait(). So they cannot interact anyhow.
They work as usual - the wait() just is a long running blocking operation, the thread pool is just a queue of runnables to run on limited pool of threads.
I'd comment on Tomasz's answer but my reputation does not allow it (yet), sorry.
I know the question is old, but for the people that still end up reading this page, have a look at Future and especially guava's ListenableFuture that lets you register callbacks and chain future together with, precisely, the purpose of not blocking your thread (and thus free the thread back to the pool for something else to use it).
All 5 threads will be blocked and application will be in un-productive state.
Adding to Tomasz answer, I would like to implement time out mechanism as follows.
Future<Long> futureResult = service.execute(myCallable);
Long result = null;
try{
result = futureResult.get(5000, TimeUnit.MILLISECONDS);
}catch(TimeoutException e){
System.out.println("Time out after 5 seconds");
futureResult.cancel(true);
}catch(InterruptedException ie){
System.out.println("Error: Interrupted");
}catch(ExecutionException ee){
System.out.println("Error: Execution interrupted");
}
Apart from TimeoutException, you can cancel Future during InterruptedException & ExecutionException. If you use submit() instead of execute(), InterruptedException & ExecutionException will be swallowed in framework itself.

Categories

Resources