StationaryTraveller StationaryTraveller - 4 years ago 110
Java Question

Interrupting a thread 'gracefully' while inside the main loop

Say i've got the following code:

public void run(){
while (true){
function1();
...
functionN();
}
}


And i wanna exit 'gracefully' - Which means for me that once i sent a shutdown signal and currently the thread is at functionK(), The thread will 'break' the loop and exit run.

So i've tried using Thread.interrupt() like this:

public void run(){
while (true){
try {
function1();
...
functionN();
} catch (InterruptedException ex) {
/* Cleanup and exit. */
}
}
}


But this doesn't work - The thread continutes to run endlessly even with interrupt flag on.

Just for the record:

public void run(){
while (!thread.isInterrupted()){
try {
function1();
...
functionN();
} catch (InterruptedException ex) {
/* Cleanup and exit. */
}
}
}


Stops the loop, But doesn't help me. Since each function does something that might take several minutes and there are a lot of different function so checking before each function whether interrupted flag is one might be costly (Especially since most of the times the application runs smoothly).

I wonder whether there is a special mechanism i can use for that kind of problem.

Answer Source

The API documentation is very clear about this:

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

So you can only rely on this exception if you're waiting for object monitors. There are a couple of other exceptions thrown by certain I/O operations but if you don't use them either, there is no other option than to check the interrupted() flag.

What you can do though is to re-organise your code: if you've got N methods that are called one after the other, is it not possible to abstract them out into a loop? More often than not it is possible to find a way to refactor code to support interruption, the exact way depends on your actual scenario. My first question would be: why does a single method run for minutes? That sounds a bit fishy (though it may be justified).

Either way, interruptibility isn't something that comes for free, you have to actively design interruption points if you want your code to be more responsive to interruption than the length of the main loop.

One more thing though: checking the interrupted() flag is most definitely NOT costly. Not when you spend minutes in your main loop, and it's a lot cheaper than constructing and handling an exception. I'd go as far as to say that you'll find very few things faster than a call to Thread.isInterrupted().

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download