Program continues to run despite InterruptedException - java

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

Related

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.

How do I interrupt a thread given a Future object?

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.

Always call Thread.currentThread().interrupt(); when catching an InterruptedException?

This IBM developerWorks article states:
“The one time it is acceptable to swallow an interrupt is when you know the thread is about to exit. This scenario only occurs when the class calling the interruptible method is part of a Thread, not a Runnable […]”.
I always implemented Runnable for my threads by now. Giving a Runnable implementation like this:
public class View() implements Runnable {
#Overload
public void run(){
Thread worker = new Thread(new Worker());
worker.start();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
worker.interrupt();
// Thread.currentThread().interrupt();
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
Is it really necessary to call Thread.currentThread().interrupt(); right before my return; statement? Doesn’t return; perform a clean enaugh exit already? What’s the benefit of calling it? The article states that it should be done because otherwise “[…] code higher up on the call stack won't be able to find out about it […]”. What’s the benefit of a thread in Thread.State.TERMINATED with interrupted flag set over one without it upon application shutdown? Can you give me an example where code outside the Runnable inspects the interrupted flag for a sensible reason?
BTW, is it a better code design to extend Thread instead of implementing Runnable?
It resets the interrupt flag. This JavaSpecialists newsletter covers this confusing topic in more detail.
In my example, after I caught the InterruptedException, I used
Thread.currentThread().interrupt() to immediately interrupted the
thread again. Why is this necessary? When the exception is thrown, the
interrupted flag is cleared, so if you have nested loops, you will
cause trouble in the outer loops
So if you know that your code is not going to be used by another component, then you don't need to re-interrupt. However I really wouldn't make that minor optimisation. Who knows how your code is going to be used/reused in the future (even by copy/paste) and consequently I would reset the flag for every interrupt.
Here is an example where return it is not enough:
public void doSomething1() {
while (someCondition1()) {
synchronized {
try {
this.wait();
} catch (InterruptedException e) {
return; // Should be Thread.currentThread().interrupt();
}
}
}
}
public void doSomething2() {
while (someCondition2()) {
doSomething1();
}
}
As the exception throw clears the interrupted state next time doSomething1() is executed the status is cleared and the thread does not terminates.
I prefer extending Thread because it gives you a better understanding of what the thread is doing, but it is not necessarily better code design.
As Brian stated ,it resets the interrupt flag but that doesn't say much. In your case it will do nothing and the View-Thread will keep on running.
When interrupting a Thread, the standard procedure is that the Thread should stop running. It won't do this automatically and you have to implement a way to stop it once it is interrupted.
Using the built-in functionality there are two options:
Have the main loop inside the try-block for the InterruptedException. This way, when it is interrupted you you will be thrown out of the loop and the method will exit.
The above can be bad if you have to save the state as it may corrupt the state. As an alternative, you can set the interrupted-flag (as said when it's thrown. re-interrupt it Interrupt the Thread
Either way, you have to check that the Thread is interrupted in your while-loop (with !Thread.currentThread().isInterrupted()-statement in the while-loop) or it may/will not exit. You're not fulfilling one of the first options and neither checking the flag, so your View-thread will keep on running after being interrupted.
Is it really necessary to call Thread.currentThread().interrupt(); right before my return; statement?
As a point, I always do. We all copy-and-paste code and swallowing the interrupt is such a serious problem that I as a rule always do it, even if the thread is about to die.
Doesn’t return; perform a clean enough exit already?
If you are sure that it is the last return before the run() method completes and the thread exits, then yes, it not technically necessary. But see above. For posterity, return; doesn't do anything with the interrupt flag.
The question is whether your View class has been wrapped. Are you sure that when you return you are exiting the Thread. Maybe someone is delegating to it. AOP may be in place to do some sort of instrumentation.
What’s the benefit of calling it? The article states that it should be done because otherwise “[…] code higher up on the call stack won't be able to find out about it […]”.
In general, it is important to not swallow the interrupt when your code is called by some sort of wrapping code (delegation, AOP, etc) which needs the interrupt flag. If you are swallowing it, the wrapper won't be able to use it. But in this case, there is no benefit.
What’s the benefit of a thread in Thread.State.TERMINATED with interrupted flag set over one without it upon application shutdown?
Nothing. Once the thread exits the interrupt state is worthless. And actually, it looks like the interrupt state isn't even persisted after the thread is dead.
Thread thread = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("caught");
}
}
});
thread.start();
thread.interrupt();
System.out.println(thread.isInterrupted());
thread.join();
System.out.println(thread.isInterrupted());
Prints:
true
caught
false
Can you give me an example where code outside the Runnable inspects the interrupted flag for a sensible reason?
I can't. There is no code outside of the thread's run() method unless someone is wrapping your runnable in other code without your knowledge.
This may happen if you are using an ExecutorService but in that case the thread's interrupt status is specifically cleared with a wt.isInterrupted() before the job is run.
So again, the reason is to do is is because it's a good pattern and that's what's important in software engineering.

is this the correct way to 'stop' a thread gracefully?

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.

How to kill a thread which has a while(true)?

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.

Categories

Resources