Is it OK to ignore InterruptedException if nobody calls interrupt()?
Solution 1
Ignoring a checked exception is never considered to be safe.
It may be ok for you at the moment, but if another programmer extends your code, he will expect the standard behaviour: the thread reacting to an interrupt call.
Also an empty catch block is dangerous in this case, since the JVM removes the interrupted flag and it should definitely be set again with
Thread.currentThread().interrupt();
in the catch block. In my opinion, this is the minimum catch implementation for InterruptedException
s. Checking for the isInterrupted
flag in a loop doesn't hurt much, either.
It is little overhead compared to your future programmer self's hassle searching a day or two for unexpected thread behaviour as you project may have grown a bit.
If you feel that your code's readability suffers from those catch implementations, you may implement your own safeSleep
utility method, which takes care of the Exception
s and sets the flag properly.
On the other hand, InterruptedException
is not thrown by the JVM itself in case of a hardware failure, it is a user indicated Exception
only. So, if you do not propagate your That's it technically. But you shouldn't underestimate the human factor and your programs evolution.Thread
s reference, there won't be any other Thread
s that are able to call Thread.interrupt()
on it.
Edit: As ruakh pointed out, there actually is a way to get a Thread
s reference and thus to schedule an Thread.interrupt()
call. That way the developer in heat may not even have to look at the class, that implements your uninterruptible Thread
. In my opinion that's even another reason, to implement proper exception handling.
Another thing: If you're not throwing an Exception
, logging such an event on a level beyond INFO
may be a good choice.
Solution 2
Instead of swallowing it, if you're so sure it will never happen, you can crash instead of ignoring it. For example, throw an Error
(or a RuntimeException
):
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new Error(e);
}
From the Javadocs for Error:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.
If you think it's worth assuming something will never happen, then if it does happen, that's an "abnormal condition" that, who knows, might just be a "serious problem".
Another way to look at this is, if someone in the future does interrupt your method, is there any chance that they will want it to continue running as if nothing had happened? I would guess no.
Solution 3
You should never swallow an exception if you think that it should never occur. It’s ok to decide not to add code handling a condition which never occurs but it shouldn’t happen silently.
The minimum you should do is:
catch(InterruptedException ex) {
throw new AssertionError(ex);
}
This ensures that whenever your assertion that this will never occur is wrong, you will notice. This pattern also applies to other unexpected exceptions, e.g. IOException
when you know that the target OutputStream
is a ByteArrayOutputStream
or the Appendable
of a Formatter
ought to be a StringBuilder
, etc.
By the way, there is an alternative to Thread.sleep
not requiring to deal with InterruptedException
at all:
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));
This method will simply return earlier when the thread has been interrupted and retain the interrupted state of the Thread
so it provides already a correct handling for the case that your code is used by someone else who does use interruption (assuming that the caller of your code checks the interrupted state then).
Solution 4
The book that I still consider the bible on these matters, Goetz et al. Java Concurrency in Practice says the following important bits in chapter 7 (Pretty much the same material is found in Goetz's developerWorks article, which has the advantage of being free, but the book is a bit more clear on some points.)
Interruption is a cooperative mechanism. One thread cannot force another to stop what it is doing and do something else; when thread A interrupts thread B, A is merely requesting that B stop what it is doing when it gets to a convenient stopping point—if it feels like it.
[...]
Only code that implements a thread’s interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests.
So, yes, you can "swallow" InterruptedException
under the circumstances you outlined.
Also an important point in the book:
Because each thread has its own interruption policy, you should not interrupt a thread unless you know what interruption means to that thread.
So you can choose your own policy like "crashing" with a RuntimeException
, AssertionError
, just logging it as a warning, or ignoring interruption altogether as long as you document this issue for whoever else might need to know. What is best depends on what your thread is really doing and you haven't provided any details on that. For example, if it's running on a rocket [say doing attitude control], you do not want to crash the JVM/rocket just because a fellow programmer [who might not even work for the same company as you, e.g. he wrote some library you call] forgot about a certain contract somewhere in his code and dumps a safely ignorable exception on yours: "The exception which occurred was not due to random failure but a design error."
Solution 5
It should not be ignored. It should either be thrown back to the caller or you should reassert the thread's interrupted status which is cleared when the exception is thrown:
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
unless you prompty exit the thread after the catch.
Here's an article about dealing with InterruptedException
s.
Hilikus
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." - M. Fowler
Updated on June 17, 2022Comments
-
Hilikus almost 2 years
If I create my own thread (i.e. not a threadpool) and somewhere I call
sleep
or any other interruptible method, is it ok to ignore the InterruptedException if I know nobody else in the code is doing an interrupt on the thread.In other words, if the thread is supposed to live as long as the JVM, meaning the thread is not interruptible, is it safe to assume that InterruptedException will never be called and therefore the exception can be swallowed?
-
kapex about 9 yearsIf you just re-throw the exception, wouldn't that have the same effect as killing the thread with the deprecated Thread.stop() method? Who will catch the exception?
-
Solomon Slow about 9 yearsWhat is "the standard behavior?" clean up and shut down?
-
Solomon Slow about 9 yearsAlso, if you have reason to believe that your code can safely ignore some exception, then you should at least call LOGGER.debug(ex), so that it will be easier to figure out what happened if your belief should somehow turn out to be wrong.
-
Zhedar about 9 years@james large in fact, there may be no standard behaviour, but an expected one. that is aborting the current process and finishing gracefully. but as always: documentation is key here.
-
user253751 about 9 yearsI normally use
AssertionError
for this, but that's mostly just a personal preference. -
Hilikus about 9 years@jameslarge for me, just printing a log message is still ignoring the exception
-
sfdcfox about 9 yearsAnd, later, when it crashes six months down the line, because you write something that needs to interrupt it, you'll remember why you decided not to silently swallow the error to begin with. Or, you'll have a subtle bug, like data not getting saved to a database, memory leaks, or whatever other resources this thread might be holding.
-
Solomon Slow about 9 years@Hilikus, I agree. Holger's answer explained why its a bad idea to ignore an exception that you think can never happen. I tacked on my comment to say something about the rare case where you know the exception will happen, and you mean to ignore it.
-
Dorus about 9 yearsUGH. This is ugly, if you are going to rethrow the
InterruptedException
, just throw theInterruptedException
itself. This is especially true for library code. If this is your application code, it really wont make any difference if you rethrown or ignore the exception anyway, since you can guarantee it's not caused in the first place. The other option is to gracefully exit your thread. -
Dan Getz about 9 years@Dorus the question was for code written inside a thread. You can't throw an
InterruptedException
fromRunnable.run()
unless it's wrapped inside something else. If you mean, "throw theInterruptedException
inside some method that you then call", sure, but then what do you do in the thread that calls it? -
Dorus about 9 yearsMmm true, once you reach thread level, crashing or gracefully ending your thread are both valid options. Got to agree. Pick what fits best.
-
Admin about 9 years+int(PI/3) for
LockSupport
- you made me learn yet another not-so-common feature of Java today... -
ruakh about 9 yearsRe: "if you do not propagate your
Thread
s reference there won't be any otherThread
s, that are able to callThread.interrupt()
on it": Threads aren't like random objects, that you can decide whether or not to propagate. The JDK offer methods for finding all threads. See stackoverflow.com/questions/1323408/… for a few approaches. -
Zhedar about 9 years@ruakh Thanks for your comment. I've corrected this in my answer.
-
randers about 8 yearsRegarding the
safeSleep
method: Instead of implementing your own, you can also use Guava'sUninterruptibles
(e.g.Uninterruptibles.sleepUninterruptibly
) -
Ranger almost 7 years"On the other hand, InterruptedException is not thrown by the JVM itself": can you support this claim by linking to documentation/specification stating this?
-
Zhedar almost 7 years@EduardWirch I think i got it from a German book by Michael Inden, which I do not have at hand right now. But a quick search brought up this SO-answer, which references the JLS section 17.2.3:
Interruption actions occur upon invocation of Thread.interrupt, as well as methods defined to invoke it in turn, such as ThreadGroup.interrupt.