Handling Interruptedexception in Java

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 the InterruptedException 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:

    1. 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.

    2. 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 an InterruptedException). In other words, it does not make sense to declare this method with throws 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 of Runnable.run does not allow for rethrowing InterruptedExceptions. Well, you signed up on implementing Runnable, which means that you signed up to deal with possible InterruptedExceptions. Either choose a different interface, such as Callable, 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 call Thread.sleep(1000). So, you need to deal with InterruptedException. For a method such as tryToReadFile 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 throw InterruptedExceptions.

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.

  1. 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.


  1. 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.


  1. 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 (say operation()) that throws an InterruptedException and you won't be able to proceed further unless this call completes. Suppose operation() throws InterruptedException 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 throws InterruptedException and you are done

  • If 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 calling interrupt() 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



Leave a reply



Submit