430

What is the difference between the following ways of handling InterruptedException? What is the best way to do it?

try{
 //...
} catch(InterruptedException e) { 
   Thread.currentThread().interrupt(); 
}

OR

try{
 //...
} catch(InterruptedException e) {
   throw new RuntimeException(e);
}

EDIT: I'd like to also know in which scenarios are these two used.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
softwarematter
  • 28,015
  • 64
  • 169
  • 263

7 Answers7

581

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.

Gray
  • 115,027
  • 24
  • 293
  • 354
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • What is the problem with the second method? – blitzkriegz Oct 20 '10 at 10:18
  • 6
    The article says that you should call `interrupt()` to preserve the interrupted status. What's the reason behind not doing this on a `Thread.sleep()`? – oksayt Feb 08 '11 at 07:54
  • 9
    I don't agree, in the case where your thread does not support interrupts, any interrupts being received indicates an unexpected condition (i.e. a programming error, bad API usage), and bailing out with a RuntimeException is an appropriate response (fail-fast). Unless it's considered part of the general contract of a thread that even if you do not support interrupts you must continue operation when you receive them. – amoe Aug 30 '13 at 10:14
  • 21
    Calling methods that throw InterruptedExceptions and say that you "don't support interrupts" seems like sloppy programming and a bug waiting to happen. Put differently; If you call a method that is declared to throw InterruptedException it should *not* be an unexpected condition if that method does in fact throw such exception. – aioobe Sep 07 '15 at 08:09
  • Is the following statement correct? _Calling `Thread.currentThread.interrupt()` is equivalent to directly jumping to the next outer `InterruptExcetion` handler_. If so, I propose to change the comment in above really nice answer respectively. – Marti Nito May 13 '19 at 17:17
  • 1
    @MartiNito, no, calling `Thread.currentThread.interrupt()` in an `InterruptedException` catch block will only set the interrupt flag. It will not cause another `InterruptedException` to be thrown / caught in an outer `InterruptedException` catch block. – aioobe May 13 '19 at 18:24
  • @aioobe. I see, thank you. I checked the code e.g. in `Future.get`. The implementation there checks if the interrupt flag of the thread is set, and if so throws a new `InterruptedException` from there immediately. Hence, I think this statement should be correct: _Calling `Thread.currentThread.interrupt()` will cause an `InterruptedException` to be thrown from the next **interruptable context**, given this context is implemented propperly._ – Marti Nito May 14 '19 at 14:42
  • Well yes, if the thread is in a `Future.get`, calling interrupt will most likely cause an `InterruptedException` to be thrown, which will be caught in the enclosing catch block. Not all blocking methods are implemented this way. There's no _guarantee_ that an `InterruptedException` will be thrown when you call interrupt, so the statement is not universally true. Check the [javadoc for interrupt](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupt--). – aioobe May 14 '19 at 15:36
  • There seems to be one important case your post is missing. Consider a slight modifications of the `printSum` example you gave: `int printSum() {try {return computeSum("myServer");} catch (InterruptedException e) {// do something sensible here}}`. If you cannot re-throw the interrupted exception, because you e.g. implement some API, in this case, resetting the interrupted status and returning some magic number does not seem to be sensible to me. In this case an unexpected condition happened that causes that the sum could not be calculated and throwing a RuntimeException seems sensible to me. – user1587520 Jul 12 '19 at 09:54
  • @amoe is right. If you don't plan to support interruption in your application then an unexpected `InterruptedException` is a bug and should be propagated with a `RuntimeException` or an `Error`. In that case it is wrong to treat `InterruptedException` as anything but a bug! And it is a perfectly valid design to call `Thread.sleep` or `Object.wait` without the intention to implement an interruption mechanism. – Lii May 07 '20 at 08:59
  • 3
    If using `Thread.currentThread().interrupt()` beware of threads that have a run loop that _doesn't_ check/clear that flag. You may need to add some code to call/check `Thread.interrupted()` at that top level/loop, to avoid staying permanently in the interrupted state. (e.g. if you have a loop with only one place that catches `InterruptedException`, and your catch block calls `Thread.currentThread.interrupt()` then subsequent invocations of that code will immediately re-trigger that exception if nothing has cleared it from the previous invocation. – Mr Weasel Aug 16 '22 at 23:38
128

As it happens I was just reading about this this morning on my way to work in Java Concurrency In Practice by Brian Goetz. Basically he says you should do one of three things

  1. Propagate the InterruptedException - Declare your method to throw the checked InterruptedException so that your caller has to deal with it.

  2. Restore the Interrupt - Sometimes you cannot throw InterruptedException. In these cases you should catch the InterruptedException and restore the interrupt status by calling the interrupt() method on the currentThread so the code higher up the call stack can see that an interrupt was issued, and quickly return from the method. Note: this is only applicable when your method has "try" or "best effort" semantics, i. e. nothing critical would happen if the method doesn't accomplish its goal. For example, log() or sendMetric() may be such method, or boolean tryTransferMoney(), but not void transferMoney(). See here for more details.

  3. Ignore the interruption within method, but restore the status upon exit - e. g. via Guava's Uninterruptibles. Uninterruptibles take over the boilerplate code like in the Noncancelable Task example in JCIP § 7.1.3.
leventov
  • 14,760
  • 11
  • 69
  • 98
mR_fr0g
  • 8,462
  • 7
  • 39
  • 54
  • 13
    *"Sometimes you cannot throw InterruptedException"* -- I'd say, sometimes it's *not appropriate* for the method to propagaet InterruptedExceptions. Your formulation seems to suggest that you should rethrow the InterruptedException whenever you *can*. – aioobe Oct 09 '14 at 11:50
  • 2
    And if you got to reading chapter 7, you'll see that there are some subtleties to this, like those in Listing 7.7, where a noncancelable task doesn't restore the interrupt *right away*, but only after it's done. Also Goetz has many co-authors to that book... – Fizz Feb 17 '15 at 00:20
  • 1
    I like your answer because it is concise, however I believe it should also state to gently and quickly return from your function in the second case. Imagine a long (or infinite) loop with a Thread.sleep() in the middle. The catch of the InterruptedException should call Thread.currentThread().interrupt() **and** break out of the loop. – Yann Vo Aug 22 '18 at 06:57
  • @YannVo I've edited the answer to apply your suggestion. – leventov Oct 17 '19 at 18:49
28

What are you trying to do?

The InterruptedException is thrown when a thread is waiting or sleeping and another thread interrupts it using the interrupt method in class Thread. So if you catch this exception, it means that the thread has been interrupted. Usually there is no point in calling Thread.currentThread().interrupt(); again, unless you want to check the "interrupted" status of the thread from somewhere else.

Regarding your other option of throwing a RuntimeException, it does not seem a very wise thing to do (who will catch this? how will it be handled?) but it is difficult to tell more without additional information.

Grodriguez
  • 21,501
  • 10
  • 63
  • 107
  • 18
    Calling `Thread.currentThread().interrupt()` sets the interrupted flag (again), which is useful indeed if we want to ensure that the interrupt gets noticed and processed on a higher level. – Péter Török Oct 20 '10 at 09:31
  • 1
    @Péter: I was just updating the answer to mention this. Thanks. – Grodriguez Oct 20 '10 at 09:32
16

The correct default choice is add InterruptedException to your throws list. An Interrupt indicates that another thread wishes your thread to end. The reason for this request is not made evident and is entirely contextual, so if you don't have any additional knowledge you should assume it's just a friendly shutdown, and anything that avoids that shutdown is a non-friendly response.

Java will not randomly throw InterruptedException's, all advice will not affect your application but I have run into a case where developer's following the "swallow" strategy became very inconvenient. A team had developed a large set of tests and used Thread.Sleep a lot. Now we started to run the tests in our CI server, and sometimes due to defects in the code would get stuck into permanent waits. To make the situation worse, when attempting to cancel the CI job it never closed because the Thread.Interrupt that was intended to abort the test did not abort the job. We had to login to the box and manually kill the processes.

So long story short, if you simply throw the InterruptedException you are matching the default intent that your thread should end. If you can't add InterruptedException to your throw list, I'd wrap it in a RuntimeException.

There is a very rational argument to be made that InterruptedException should be a RuntimeException itself, since that would encourage a better "default" handling. It's not a RuntimeException only because the designers stuck to a categorical rule that a RuntimeException should represent an error in your code. Since an InterruptedException does not arise directly from an error in your code, it's not. But the reality is that often an InterruptedException arises because there is an error in your code, (i.e. endless loop, dead-lock), and the Interrupt is some other thread's method for dealing with that error.

If you know there is rational cleanup to be done, then do it. If you know a deeper cause for the Interrupt, you can take on more comprehensive handling.

So in summary your choices for handling should follow this list:

  1. By default, add to throws.
  2. If not allowed to add to throws, throw RuntimeException(e). (Best choice of multiple bad options)
  3. Only when you know an explicit cause of the Interrupt, handle as desired. If your handling is local to your method, then reset interrupted by a call to Thread.currentThread().interrupt().
nedruod
  • 1,122
  • 2
  • 9
  • 19
  • +1 for your summary (and also for the note that InterruptedException should've been a RuntimeException in the first place). `Thread.currentThread().interrupt()` as a "default handling mechanism" could be very dangerous leading to unintentional busy-loops and so it's rightfully mentioned only as a last-resort option that should be done when you know what you're doing (and why) – mitchnull Oct 26 '22 at 15:13
  • btw, an "elegant" way to implement option 2 is to add `@SneakyThrows(InterruptedException.class)` lombok annotation to your method :) – mitchnull Oct 26 '22 at 15:15
14

To me the key thing about this is: an InterruptedException is not anything going wrong, it is the thread doing what you told it to do. Therefore rethrowing it wrapped in a RuntimeException makes zero sense.

In many cases it makes sense to rethrow an exception wrapped in a RuntimeException when you say, I don't know what went wrong here and I can't do anything to fix it, I just want it to get out of the current processing flow and hit whatever application-wide exception handler I have so it can log it. That's not the case with an InterruptedException, it's just the thread responding to having interrupt() called on it, it's throwing the InterruptedException in order to help cancel the thread's processing in a timely way.

So propagate the InterruptedException, or eat it intelligently (meaning at a place where it will have accomplished what it was meant to do) and reset the interrupt flag. Note that the interrupt flag gets cleared when the InterruptedException gets thrown; the assumption the Jdk library developers make is that catching the exception amounts to handling it, so by default the flag is cleared.

So definitely the first way is better, the second posted example in the question is not useful unless you don't expect the thread to actually get interrupted, and interrupting it amounts to an error.

Here's an answer I wrote describing how interrupts work, with an example. You can see in the example code where it is using the InterruptedException to bail out of a while loop in the Runnable's run method.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
5

I just wanted to add one last option to what most people and articles mention. As mR_fr0g has stated, it's important to handle the interrupt correctly either by:

  • Propagating the InterruptException

  • Restore Interrupt state on Thread

Or additionally:

  • Custom handling of Interrupt

There is nothing wrong with handling the interrupt in a custom way depending on your circumstances. As an interrupt is a request for termination, as opposed to a forceful command, it is perfectly valid to complete additional work to allow the application to handle the request gracefully. For example, if a Thread is Sleeping, waiting on IO or a hardware response, when it receives the Interrupt, then it is perfectly valid to gracefully close any connections before terminating the thread.

I highly recommend understanding the topic, but this article is a good source of information: http://www.ibm.com/developerworks/java/library/j-jtp05236/

TheIT
  • 11,919
  • 4
  • 64
  • 56
1

I would say in some cases it's ok to do nothing. Probably not something you should be doing by default, but in case there should be no way for the interrupt to happen, I'm not sure what else to do (probably logging error, but that does not affect program flow).

One case would be in case you have a task (blocking) queue. In case you have a daemon Thread handling these tasks and you do not interrupt the Thread by yourself (to my knowledge the jvm does not interrupt daemon threads on jvm shutdown), I see no way for the interrupt to happen, and therefore it could be just ignored. (I do know that a daemon thread may be killed by the jvm at any time and therefore are unsuitable in some cases).

EDIT: Another case might be guarded blocks, at least based on Oracle's tutorial at: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

Bjarne Boström
  • 227
  • 1
  • 4
  • 14
  • 1
    This is bad advice. I have extreme trouble thinking of any task that is so important as to ignore Interrupts. Oracle was likely just lazy and didn't want to add (more) clutter to Thread.sleep() invocation. Unless you know why your thread is getting interrupted, you should stop whatever you are doing (either return, or rethrow an exception to help your thread die as fast as possible). – Ajax Jan 28 '16 at 03:33
  • 1
    That's why I said sometimes. Also because it was not suggested yet and it is perfectly fine in **some** cases in my opinion. I guess it depends what kind of software you are building, but if you have a 24/7 worker thread that should never ever stop (apart from JVM shutting down), I would treat interrupts from e.g. taking an item from a BlockingQueue as an error (i.e. log) since "it should not happen" and try again. Of cource I would have separate flags to check program termination. In some of my programs JVM shutting down is not something that should happen under normal operation. – Bjarne Boström Jan 28 '16 at 11:36
  • 1
    Or put in another way: In my opinion it is better to risk having an extra error log statements (and e.g. having mail sent on error logs) than having an application which should be running 24/7 to stop because of an interruptexception, for which I see no way of happening during normal conditions. – Bjarne Boström Jan 28 '16 at 11:47
  • Hm, well, your use cases may differ, but in an ideal world, you don't just terminate because you were interrupted. You stop taking work off the queue and let THAT thread die. If the scheduler of threads is also interrupted and told to shutdown, then the JVM is terminating, and its game over. In particular, if you send kill -9 or are otherwise trying to take down your mail server or whatever, then it will ignore you until you force quit, thus preventing other parts of your code from graceful shutdown. Force kill while writing to disk or db, and I'm sure wonderful things will happen. – Ajax Jan 30 '16 at 15:29