Handling InterruptedException in Java
What is the difference between the following ways of handling InterruptedException? What is the best way to do it?
You've probably come to ask this question because you've called a method that throws InterruptedException
.
First of all, you should see throws InterruptedException
for what it is: A part of the method signature and a possible outcome of calling the method you're calling. So start by embracing the fact that an InterruptedException
is a perfectly valid result of the method call.
Now, if the method you're calling throws such exception, what should your method do? You can figure out the answer by thinking about the following:
Does it make sense for the method you are implementing to throw an InterruptedException
? Put differently, is an InterruptedException
a sensible outcome when calling your method?
If yes, then
throws InterruptedException
should be part of your method signature, and you should let the exception propagate (i.e. don't catch it at all).Example: Your method waits for a value from the network to finish the computation and return a result. If the blocking network call throws an
InterruptedException
your method can not finish computation in a normal way. You let theInterruptedException
propagate.int computeSum(Server server) throws InterruptedException {
// Any InterruptedException thrown below is propagated
int a = server.getValueA();
int b = server.getValueB();
return a + b;
}If no, then you should not declare your method with
throws InterruptedException
and you should (must!) catch the exception. Now two things are important to keep in mind in this situation:Someone interrupted your thread. That someone is probably eager to cancel the operation, terminate the program gracefully, or whatever. You should be polite to that someone and return from your method without further ado.
Even though your method can manage to produce a sensible return value in case of an
InterruptedException
the fact that the thread has been interrupted may still be of importance. In particular, the code that calls your method may be interested in whether an interruption occurred during execution of your method. You should therefore log the fact an interruption took place by setting the interrupted flag:Thread.currentThread().interrupt()
Example: The user has asked to print a sum of two values. Printing "
Failed to compute sum
" is acceptable if the sum can't be computed (and much better than letting the program crash with a stack trace due to anInterruptedException
). In other words, it does not make sense to declare this method withthrows InterruptedException
.void printSum(Server server) {
try {
int sum = computeSum(server);
System.out.println("Sum: " + sum);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
System.out.println("Failed to compute sum");
}
}
By now it should be clear that just doing throw new RuntimeException(e)
is a bad idea. It isn't very polite to the caller. You could invent a new runtime exception but the root cause (someone wants the thread to stop execution) might get lost.
Other examples:
Implementing
Runnable
: As you may have discovered, the signature ofRunnable.run
does not allow for rethrowingInterruptedExceptions
. Well, you signed up on implementingRunnable
, which means that you signed up to deal with possibleInterruptedExceptions
. Either choose a different interface, such asCallable
, or follow the second approach above.
Calling
Thread.sleep
: You're attempting to read a file and the spec says you should try 10 times with 1 second in between. You callThread.sleep(1000)
. So, you need to deal withInterruptedException
. For a method such astryToReadFile
it makes perfect sense to say, "If I'm interrupted, I can't complete my action of trying to read the file". In other words, it makes perfect sense for the method to throwInterruptedExceptions
.String tryToReadFile(File f) throws InterruptedException {
for (int i = 0; i < 10; i++) {
if (f.exists())
return readFile(f);
Thread.sleep(1000);
}
return null;
}
This post has been rewritten as an article here.
How does one correctly handle InterruptedException that may not be passed to client code?
Let me discuss each one of your available options.
- Ignore interrupted exception
This is wrong. It is never right to swallow the exception when you are implementing something like a library which other users will come to rely upon. In these cases, it would never be prudent to swallow an exception unless you propagate it as a different exception which provides more meaningful information to the client. An InterruptedException
is basically a request to cancel your thread and this information should never be suppressed from the client irrespective of whether the lock would be unlocked later. The client needs to know that someone wants the unit of work being carried out by this thread to be stopped.
- Wrap in
RuntimeException
No. This is wrong as well for exactly the same reason as above. the reason for propagating an InterruptedException
is to let a client know that a request has been made to cancel an executing thread and hence wrapping it in a RuntimeException
is wrong because this information is lost.
- Use/force
Thread.currentThread().interrupt()
call
This may be right or wrong depending on the use case. Ask yourself if it would be ok for you to propagate the InterruptedException.
If it is ok to do so (it is not in your case but), then you can declare that your method throws
InterruptedException
and let the callers above worry about what needs to be done. This would typically be the case when you make a call to a method (sayoperation()
) that throws anInterruptedException
and you won't be able to proceed further unless this call completes. Supposeoperation()
throwsInterruptedException
then there is nothing much you can do other than propagating this exception. So you shouldn't catch the exception. In this case just declare that your method throwsInterruptedException
and you are doneIf it is not ok to do so then the correct way to handle it would be to force an
interrupt()
call. Using this you suppress the exception but you still give the client the option of checking the flag to see if an interruption request was made. And you are right. This requires the client side to poll rather than processing the interruption. But this is not wrong. If you don't want clients to poll then propagating the exception would have been the better option. But this is not always possible and your example is one such use case. And there are many cases where a thread of execution can return some meaningful information even when it is Interrupted. So in this cases the exception is suppressed but the information that there was a request for termination can still be passed above by callinginterrupt()
method. So the client can either just use the result that was returned from a partial computation or poll to check if the interrupt flag was set depending on the use case. So you are giving the client more flexibility by doing this.
Best way to handle InterruptedException
If you have a dedicated thread that is looping and polling, that sounds to me like something that needs to be terminated when the program ends; unless it is a daemon thread (implying you are happy with it going away with no chance to cleanup or close resources) it needs to be able to handle interruption. Using WatchService seems like a good idea, but the code that uses the WatchService still has to know how to handle interruption.
If you are writing a Runnable or Callable that sleeps, you can use the InterruptedException to exit whatever looping you're doing, or you can catch the exception and restore the interrupt flag so that the next check of the interrupt flag (using Thread.currentThread().isInterrupted()
) can see that the thread has been interrupted:
while(!Thread.currentThread().isInterrupted()){
//do something
try{
Thread.sleep(5000);
} catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
Alternatively you can use the InterruptedException to get out of the loop:
try {
while (!Thread.currentThread().isInterrupted()) {
// do something
Thread.sleep(5000);
}
} catch (InterruptedException e) {
// flag value is not used here
Thread.currentThread().interrupt();
}
If you are developing an object that you expect to nest inside other objects, then throw the exception and add it to the method signature. As an example look at the API doc for classes in the java.util.concurrent packages, like BlockingQueue, see how methods like put and offer throw InterruptedException. When objects made for concurrency are composed together they need to cooperate (and make sure they don't lose track of interrupted status) in order to make sure that they can clean up and terminate in a responsive manner.
How to handle InterruptedException of BlockingQueue?
It depends. Are there places where you intentionally interrupt the thread, for example to tell it to finish up (for example during shutdown)? If not, you just need to handle possible spurious interrupts that will wake up the thread. If you don't want the processing to be affected, just ignore them. They're in absolutely no way fatal exceptions, and you don't need to log them (especially as errors).
How to handle Java InterruptedException without business logic break?
The interrupt will come from some other place in your program. It's not something the OS is going to do of its own volition.
Typically interrupts indicate that the code should get out of there. This could be handled by throwing a more appropriate exception.
Currently your code, once interrupted, will keep interrupting itself. This is solvable by keeping the interrupt state in a local flag.
private StorageConnection allocateConnection() {
boolean interrupted = false;
boolean allocated = false;
while( !allocated ){
try {
semaphore.acquire();
allocated = true;
} catch (InterruptedException e) {
interrupted = true;
}
}
StorageConnection connection = connectionQueue.poll();
// OTHER LOGIC
if (interrupted) {
Thread.currentThread().interrupt();
}
return connection;
}
It is not an entirely unreasonable attitude to simply clear and ignore the interrupt.
Related Topics
Converting Array to List in Java
Initial Bytes Incorrect After Java Aes/Cbc Decryption
Compiling a Java Program into an Executable
How to Convert Strings to and from Utf8 Byte Arrays in Java
How to Know If Other Threads Have Finished
How to See Jit-Compiled Code in Jvm
Java: Parse Int Value from a Char
Java Io Implementation of Unix/Linux "Tail -F"
Java: Difference Between the Setpreferredsize() and Setsize() Methods in Components
Remove Diacritical Marks (Ń Ǹ Ň ñ Ṅ Ņ Ṇ Ṋ Ṉ ̈ Ɲ Ƞ ᶇ ɳ ȵ) from Unicode Chars
Java, Classpath, Classloading => Multiple Versions of the Same Jar/Project
How to Get a List of Dates Between Two Dates in Java