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.
Related
I want to start a thread and cancel it if it doesn't finish within 5 seconds:
private final class HelloWorker implements Callable<String> {
public String call() throws Exception {
while(true) {
if (Thread.isInterrupted()) {
return null;
}
}
return performExpensiveComputation();
}
private String performExpensiveComputation() {
// some blocking expensive computation that may or may not take a very long time
}
}
private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Future<String> future = executorService.submit(new HelloWorker());
try {
String s = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("cancelled: " + future.isCancelled() + "done: " + future.isDone());
executorService.shutdown();
try {
System.out.println("try to terminate: " + executorService.awaitTermination(60, TimeUnit.SECONDS));
} catch (Exception ex) {
// ignore
}
}
However it looks like the awaitTermination returns false. Is there a way for me to check why an ExecutorService won't terminate? Can I figure out what threads are still running?
There is no safe way to stop a running thread without disturbing the stability of the rest of the process. This is why Thread#stop has been deprecated a long time ago, and why Executor Services only use the soft, cooperative Thread#interrupt mechanism.
Your thread will have to actively check if an interrupt has been requested and perform proper cleanup before ending. Alternatively, the thread will call some interruptible JDK methods, which will throw InterruptedException, which the tread will properly honor and end itself.
Why Future.cancel() doesn't work the way you think it does
Future cancel removes the task from the running queue. If your task is already running it won't stop it. So cancel() is a different concept that interrupting. As the Javadocs say:
Attempts to cancel execution of this task. This attempt will fail if
the task has already completed, has already been cancelled, or could
not be cancelled for some other reason. If successful, and this task
has not started when cancel is called, this task should never run. If
the task has already started, then the mayInterruptIfRunning parameter
determines whether the thread executing this task should be
interrupted in an attempt to stop the task.
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html#cancel(boolean)
What you are asking is how to interrupt. Fortunately, when you call Future.cancel() it will call the interrupt method. But you'll need to allow it with the mayInterruptIfRunning flag and will need to handle interrupts correctly (see below).
Why interrupt?
Interrupting threads in Java is useful when you have a long running task that you now need to stop, or when you have a daemon that you need to turn off, and other examples.
How to interrupt
To interrupt you call interrupt() on the thread. This is a cooperative process, so your code has to be ready for it. Like this:
myThread.interrupt();
Responsible code
Your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.
Should I use isInterrupted() or interrupted()
You should prefer interrupted() because:
Your code should reset the interrupt flag because if you don't the thread you are using could go back to a thread pool with an interrupted state causing problems (of course, that's a bug in the thread pool code, you won't get that behavior if you use Executors.newFixedThreadPool() for example. But other threading code could have it.
As another answer stated, the clearing of the interrupted flag indicates that you've received the message and are taking action. If you leave it on true, the after a while caller can assume you won't respond to it in a timely manner.
Why interrupt() why not some other flag in my code?
Interrupt is the best mechanism for interruption because our code can be ready for it. If we find code that is just catching and ignoring the InterruptExceptions or not checking for interrupted() in its body then we can correct those mistakes and make our code always cleanly interruptible without creating arcane dependencies on non-standard mechanisms in your code.
Unfortunately Joshua Block proposed the opposite in his famous book Effective Java, Second Edition. But enabling the interrupt() method to work as intended is much better, because this code is used by the Java standard library as explained above. A custom interruption method would not be.
In my application each request has its own thread. I use JMX/JConsole to monitor them, measure the elapsed time. If a a request needs too much time I'd like to stop it by interrupting the underlying thread.
In a method that I call from JConsole I iterate over the list of threads and call interrupt() on the right instance.
However simply calling the interrupt() method on the thread instance only sets a flag, so I need to throw an InterruptedException, too.
But this InterruptedException will apply to currentThread instead of the thread I actually want to stop. Any hint how to shut down the flagged thread?
while (iterator.hasNext()) {
RequestHolder rh = iterator.next();
if (rh.getThread().getId() == threadId) {
rh.getThread().interrupt();
if(rh.getThread().isInterrupted()){
throw new InterruptedException();
}
}
}
But this InterruptedException will apply to currentThread instead of the thread I actually want to stop.
You can check the interruption status of any thread using isInterrupted. However, it is not recommended as a black-boxed approach if you don't know how and when the interruption gets consumed.
Any hint how to shut down the flagged thread?
You cannot cleanly shutdown a thread from another thread.
But it is very simple. In the threads that are running, check for Interruption regularly, such as in loop catch InterruptedException for blocking functions. When you see the interruption in the thread, make it terminate itself. In a sense, the Threads implement their own termination policy.
There is no benefit to throwing InterruptedException. Your if (rh.getThread().isInterrupted()) block can be removed.
Each thread must monitor its own interrupted state, and must exit gracefully when it sees that it has been interrupted.
Usually the code looks something like this:
try {
InputStream in = socket.getInputStream();
while (in.read(buffer) >= 0) {
if (Thread.interrupted()) {
logger.log(Level.FINE, "Interrupted; exiting");
break;
}
// Process request buffer here
}
} catch (InterruptedIOException e) {
logger.log(Level.FINE, "Interrupted; exiting", e);
}
If you are using Channels, you'll want to catch ClosedByInterruptException as well.
you can pass the reference of the thread to be terminated in the constructor of the thread responsible for performing the termination of the first one. Then you can destroy the thread using its reference from another thread.
instead of continuous checking of variable inside a loop:
class Tester {
public static void main() {
Try t = new Try();
Thread.sleep(10); //wait for 10 milliseconds
t.interrupt(); // 'interrupt' i.e stop the thread
}
}
public class Try extends Thread {
public void interrupt() {
//perform all cleanup code here
this.stop();
/*stop() is unsafe .but if we peform all cleanup code above it should be okay ???. since thread is calling stop itself?? */
}
}
In order to perform interrupt in a good manner you should poll for the "interrupted()" method inside the thread that is being interrupted.
Just be aware that calling interrupted() method resets the interruption flag (that is set when calling interrupt()).
I guess the bottom line is that you have to continuously poll inside the thread in order to perform a graceful interruption.
You should never ever call .stop() on a Thread, period. It's not enough for the thread to perform its own cleanup. Since calling .stop() immediately releases all monitors, other threads may see shared data in an inconsistent state which may result in almost impossible to track errors.
Use Thread.interrupt() method instead of Thread.stop(). In the interrupted thread you can catch the InterruptedException and do any cleanup required.
A similar questions has already been asked here, you can find a code sample there too.
I am trying to close all my thread in my threadpool.
Usually I try:
while(!Thread.currentThread().isInterrupted()) {...
To close the while loop...
But I have one Thread which only consists about
while(!Thread.currentThread().isInterrupted()) {//which is true
This is how I close the threads:
pool.shutdownNow();
So how would you close such a Thread?
You can add a volatile boolean flag.
public class Worker implements Runnable {
volatile boolean cancel = false;
#Override
public void run() {
while (!cancel) {
// Do Something here
}
}
public void cancel() {
cancel = true;
}
}
Now you can just call
worker.cancel();
Update:
From Java doc of 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.
here 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.
So either you will have to define your interruption policy by preserving the interrupts
catch (InterruptedException ie) {
// Preserve interrupt status
Thread.currentThread().interrupt();
}
Instead of that you might use a self created flag as condition for the while loop.
public class MyClass implements Runnable
{
private volatile boolean running = true;
public void stopRunning()
{
running = false;
}
public void run()
{
while (running)
{
}
// shutdown stuff here
}
}
Now, to stop it, just call:
myClassObject.stopRunning();
This will let the code finish normally.
If you have implemented this as you have described, it should just work.
When you call pool.shutdownNow() it is supposed to interrupt all worker threads that are currently active. Assuming that the application specific run() methods check the interrupted flag and terminate themselves when they find it set, your threads should shutdown.
There is really no need to add a different mechanism using an ad hoc cancel flag ... or some such.
Incidentally, there are a couple reasons why interrupt() is better than ad hoc cancellation:
Standard APIs like ExecutorService use it.
Various low-level API methods like sleep, wait, join and some I/O methods are sensitive to it.
If you are using a java.util.concurrent ExecutorService implementation, then it will definitely send an interrupt signal to all the threads in its thread pool. The problem with your rogue task may be that the loop doesn't in fact iterate, but blocks somewhere within, so the interrupted status is not getting checked at all.
Yet another problem you may have: the while loop runs some code that catches InterruptedException without handling it properly, effectively swallowing the interrupt signal. This is a common coding mistake and in most cases due to the ugly truth that InterruptedException is checked.
I started learning java and I am now at the concurrency chapter. After reading some stuff about concurrency I tried an example of my own.
public class Task implements Runnable{
public void run() {
while(!Thread.interrupted()) {
try {
System.out.println("task");
TimeUnit.SECONDS.sleep(2);
}catch (InterruptedException e) {
System.out.println("interrupted");
}
}
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Task());
TimeUnit.SECONDS.sleep(10);
exec.shutdownNow();
}
The problem is that i was expecting to see the following output:
task
task
task
task
task
interrupted
but after I get this, the program continues printing until I close it.
So, my question is what am I doing wrong? why does the program continues printing?
When you shutdown the executor, it tries to stop its running tasks by interrupting them. This causes an InterruptedException to be thrown, but you just swallow it and continue. You should return in your catch clause, and/or reset the interrupted status of the thread by calling Thread.currentThread.interrupt(), which will reset the interrupted status and exit the loop.
The section about interrupts in the Java tutorials about concurrency explain the problem quite well:
The Interrupt Status Flag
The interrupt mechanism is implemented using
an internal flag known as the interrupt status. Invoking
Thread.interrupt sets this flag. When a thread checks for an interrupt
by invoking the static method Thread.interrupted, interrupt status is
cleared. The non-static isInterrupted method, which is used by one
thread to query the interrupt status of another, does not change the
interrupt status flag.
By convention, any method that exits by throwing an
InterruptedException clears interrupt status when it does so. However,
it's always possible that interrupt status will immediately be set
again, by another thread invoking interrupt.
So when you catch the InterruptedException within the loop, the interrupted status is already reset and thus, the next call of Thread.interrupted() will return false, which in turn keeps the while loop running. To stop the loop, you have the following options:
Use break to exit the loop
Use return to exit the whole method
Move the try-catch-block to outside the while loop (as suggested by Nathan Hughes)
Call interrupt() on the current thread to set the interrupted flag again
Use a separate boolean to control the loop and set that flag accordingly in the catch-block
Make the task a recurring task by using a ScheduledExecutorService and dropping the loop from the run-method of your Runnable
You're still in the while loop, add a break or some other way out of the loop.
catch (InterruptedException e) {
System.out.println("interrupted");
break;
}
Threading in Java is kind of a cooperative activity, you've been asked to stop, but you need to be polite enough to actually do it. This allows the thread time to tidy its affairs before its demise.
As is explained in detail by Simon and Amir, your loop termination condition is surprisingly not sufficient.
"There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so if any tasks mask or fail to respond to interrupts, they may never terminate."
source : http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()