What if the interruptee isn't doing a blocking call?
In the above example, you may be thinking, "what if the call to interrupt() happens
while the other thread is printing the message (rather than in the Thread.sleep() call)?".
Well, it turns out not to matter in this case. If the interruptee is not in a blocking method, then:
- interrupt() will set an interrupted flag on the interruptee;
- the next time the thread makes a blocking call such as
Thread.sleep(), that call will immediately
throw the InterruptedException.
So provided that the interrupted thread periodically calls a blocking call
such as Thread.sleep(), the interruption mechanism still works.
What if the interrupted method isn't ever (or soon) going to call a blocking method like
like sleep() or wait()? In this case:
- interrupt() will not automatically interrupt the thread
if it does not make any blocking calls;
- but we can manually check for the interrupted flag and implement
cancellation ourselves.
How to handle InterruptedException?
A common piece of bad program design is to "micro-manage" InterruptedException (and indeed,
exceptions in general), by catching it and "pretending nothing happened". But in a good design, like any
exception, it should be dealt with cleanly.
What exactly to do with InterruptedException can depend on the program and
situation, of course, but as a rule of thumb:
An InterruptedException should cause the overall task to be cancelled.
This generally means:
- inside the run() method of a thread (or the Runnable
run by a thread), InterruptedException should generally cause the run()
method to terminate (as in the example above)— here, it arguably doesn't matter
whether you also, say, log it or take some other action;
- inside the run() method of a Runnable passed to another JDK utility class
(such as an Executor), it's generally best to set the thread's interrupted status
again, so that the consuming class can detect the interruption and take appropriate action
(JDK classes that consume Runnables generally will do this):
public class MyRunnable implements Runnable() {
BlockingQueue pendingStrings;
public void run() {
try {
while (true) {
String str = pendingStrings.take();
...
}
} catch (InterruptedException iex) {
Thread.currentThread().interrupt();
}
}
}
This is necessary because catching InterruptedException clears the
thread's interrupted status, so the caller would otherwise have no way
of knowing that the interruption occurred.
- in a utility method that makes a blocking call, it's usually best
to let the method throw the InterruptedException back up to the caller.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.