Reputation: 10331
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?
Upvotes: 54
Views: 28753
Reputation: 3510
Ignoring a checked exception is never considered to be safe.
It may seem okay for you at the moment, but if any other programmer uses your code/API, they should expect the standard behaviour:
Which is, the thread "reacting" to an interrupt call, but with whatever "reaction" the thread's documentation describes.
I mean it's up to the thread's developer to both decide and document exactly how a thread handles an interrupt, and Java has not any pre-defined rule, but you should document your thread's "reaction" (with Documentation comments).
For example, the InterruptedException
is only thrown from blocking methods (like Thread.sleep(...)
), but never from normal lines of code (meaning the interrupt is simply ignored by default), which allows developers to choose (and document) thread's reaction, like:
Which takes time for development, if not already supported.
Thread.currentThread().interrupt()
in catch-block.Which simulates interrupt happening while normal code was running.
java.lang.Error
(or sub-class), and passing InterruptedException
-instance as cause
.Which unless documented, is least desired or expected.
To explain postpone; An empty catch block is dangerous with InterruptedException
, since the JVM removes the interrupted flag, and it should definitely be set again in the catch block, like:
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
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.
Upvotes: 40
Reputation: 9152
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.
Another alternative would be postponing, like:
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// ... do some work ...
if (Thread.currentThread().isInterrupted()) {
// Handle if possible, and was expected,
// else, throw new `InterruptedException`.
}
Note that above example-code does not do "
if (Thread.interrupted()) {
", because that would clear the interrupt flag of the thread (which is a bad pattern).
Upvotes: 35
Reputation: 72884
It should not be ignored. It should either be thrown back to the caller, or you should reassert the thread's interrupted status, because staid status gets cleared when the InterruptedException
was thrown:
} catch (InterruptedException e) {
// Restores the interrupted flag status.
Thread.currentThread().interrupt();
}
Unless you promptly exit the thread after the catch.
Here's an article about dealing with InterruptedException
s.
The InterruptedException
is only thrown from blocking methods (like Thread.sleep(...)
), but never from normal lines of code,
and it's up to the programmer to decide exactly how a thread responds to an interrupt.
For example, there was a project which just did document it, like:
public class MyTask {
// ...
/**
* Waits for result to be use ready.
* <br>
* <br>
* <b>Warning:</b> instead of throwing {@link InterruptedException},
* returns {@code null}, and if that is undesired, do something like:
*
* <pre>{@code
* MyResult result = myTask.await(...);
* if (Thread.currentThread().isInterrupted()) {
* throw new InterruptedException();
* }
* }</pre>
*
* @param timeout Duration to wait at most.
* @param unit Type of duration.
*/
public MyResult await(long timeout, TimeUnit unit) {
try {
return /* ... */;
} catch (InterruptedException e) {
// Restores the interrupted flag status.
Thread.currentThread().interrupt();
}
return null;
}
}
Note that above doc-block's code does not do
if (Thread.interrupted()) {
, because that would clear the interrupt flag on the thread (which is a bad pattern).
Upvotes: 8
Reputation: 5203
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."
Upvotes: 14
Reputation: 614
I think, ignoring InterruptedException is safe or not, depends upon what you are doing in that thread. If there is any scenario when an unwanted interrupt to your thread can leave System or any resource in unwanted state (dirty, locked, not released which can cause leaking resource) then its your responsibility to handle the InterruptedException and you should not ignore it. It's up to you whether you want your to make your thread Interruptible or not.
In other words Interrupt mechanism is mainly used for implementing the cancellation policies and task clean up. Is you don't have anything to clean in task or you dont have any specific task cancellation policies, ignoring IntrruptedException may not sound politically correct but is OK.
Upvotes: 1
Reputation: 200256
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 thrown and therefore the exception can be swallowed?
I understand your pain, the proliferation of boilerplate try-catch blocks with no business value hurts the code.
If the code where you intend to swallow the exception is entirely under your control, and if it is just client code (it will never be reused in context other than your own), then it is safe to swallow the exception. Note that there are a lot of ifs there.
If you happen to work with Java 8, you have another option, described here: wrap your code inside an uncheckCall(() -> { ... })
block. This lets the code block throw the InterruptedException
without declaring it. As explained in the linked answer, this should be handled with extreme care, but it has the potential of making your code quite clean.
Upvotes: 2
Reputation: 298539
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).
Upvotes: 18
Reputation: 1034
If your Projekt grows and gets more complex, it's getting harder to say that definitely no one would call the interrupt method. If someone would call this method some day and an InterruptedException occurs it's getting really hard to debug this if you're not at least logging it somewhere.
Upvotes: 7