Saturday, September 16, 2006

Don't swallow InterruptedException. Call Thread.currentThread().interrupt() instead.

Have you ever written the following code?
try {
doSomething();
} catch(InterruptedException swallowed) {
// BAD BAD PRACTICE, TO IGNORE THIS EXCEPTION
// just logging is also not a useful option here....
}

I have! I newer knew what the heck to do with those annoying InterruptedException when I simply wanted to call Thread.sleep(..). What is this InterruptedException? Why is it thrown? Why can't I ignore it?

Before I explain the whys, here is what you should do (if you don't re-throw):
try {
doSomething();
} catch(InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}


What is the InterruptedException?

There is no way to simply stop a running thread in java (don't even consider using the deprecated method stop()). Stopping threads is cooperative in java. Calling Thread.interrupt() is a way to tell the thread to stop what it is doing. If the thread is in a blocking call, the blocking call will throw an InterruptedException, otherwise the interrupted flag of the tread will be set. A Thread or a Runnable that is interruptable should check from time to time Thread.currentThread().isInterrupted(). If it returns true, cleanup and return.

Why is it InterruptedException thrown?

The problem is that blocking calls like sleep() and wait(), can take very long till the check can be done. Therefore they throw an InterruptedException. However the isInterrupted is cleared when the InterruptedException is thrown! (I have some vague idea why this is the case, but for whatever reason this is done, that is how it is!)

Why can't InterruptedException be simply ignored?

It should be clear by now: because ignoring an InterruptedException means resetting the interrupted status of the thread. For example, worker threads take runnable from a queue and execute they may check the interrupted status periodically. If you swallow it the thread would not know that it was interrupted and would happily continue to run.

Some more thoughts
Unfortunately it is not specified that Thread.interrupt() can only be used for cancellation. It can be used for anything that requires to set a flag on a thread. So, ending your task or runnable early might be the wrong choice, if the interrupted status is used for something else. But common practice is to use it for cancellation. But even if it is used for something else, you code does not have the right to reset the interrupt flag (unless you are the owner of the thread).

To learn more read the nice article Dealing with InterruptedException by Brian Goetz.

Or read Java Concurrency in Practice By BriaBrian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, and Doug Lea. It's a great book! If you program in java 5 this book is a must read!. I bought the book after I read Brians artikle. I have not yet read the entire book, but what I have read impresses me. It gives a lot of theorie and options. Very competent and complete, but I'm missing a set of simple patterns for concurrent programming. I'm looking forward to Doug Leas 3rd edition of Concurrent Programming in Java

Summary: If you don't know what to do with an InterruptedException call Thread.currentThread().interrupt()

15 comments:

  1. Firstly, .interrupt() does not mean 'quit'. It means, well, interrupt. It's a way of notifying that your thread needs to do something, be it start again, cancel, quit, reiterate, reload config file ... it's basically the same as kill -HUP, which is interpreted in a number of different ways depending on the program.

    Secondly, why catch it at all? Propagate the exception upwards. That's good practice for pretty much any exception that you don't know what to do with.

    ReplyDelete
  2. Wow - get a clue dude. That is the exactly wrong advice of what to do regarding InterruptedException!!!

    Here's the correct answer:

    1) DON'T call Thread.currentThread().interrupt()!!! Your thread was already interrupted, which was why you received the InterruptedException in the first place. Why one earth would you want to interrupt it again?!?!? Not to mention that you're telling the thread that was already interrupted to then go and interrupt itself!!!! Duh!

    2) If you've coded your thread loops properly with a termination condition (e.g., while (!finished)) then doing nothing when you receive an InterruptedException is a perfectly reasonable thing to do. You told a thread to block on some operation until some condition was met (e.g., it was given some data). However, someone else wants to interrupt the operation before that condition was met. (Most likely a thread shut-down process of some sort.) So your thread gets woken up without its required condition being met. So what? Check whether the thread is supposed to terminate or keep running. If it should terminate (i.e., it's being shut down) then let it exit the thread loop and die. If not, then let it loop again and go back to blocking.

    Sheesh! Have some clue what you're talking about before you write something like this in public.

    ReplyDelete
  3. Alex, I agree, re-trow is the best solution. But there are cases, when you cannot propagate the interrupted exception. In these cases it would get swallowed if you don't re-throw and you don't call interrupt.

    But if you don't know what the meaning of the -HUP signal is, you should better not swallow it.

    Michael

    ReplyDelete
  4. Anonymous, good that you are anonymous, because you should maybe read the documentation before you blame me of not understanding what I am talking about.

    1) In the documentation of Thread.sleep(long) (as in any other method that throws InterruptedExceptin) it says: "The interrupted status of the current thread is cleared when this exception is thrown".

    2) I agree, that it is not reliable to use interrupt to terminate your operation. However, the interrupt flag might mean something to someone outside your scope. By catching the exception and not restoring the interrupted state you are swallowing important information.....

    Sheesh! Have some clue what you're talking about before you write something like this in public. ;-)

    ReplyDelete
  5. There is another solution to handle InterruptedException when you cannot throw it. It's possible to wrap the InterruptedException into a RuntimeExcpetion. This might help in cases where you don't want to interrupt the whole thread.

    ReplyDelete
  6. I think Anonymous is at least partly right. The interrupted status doesn't seem like very reliable information exactly because how many complex scenarios there are that can clear it. For example, one query method also clears it:

    "public static boolean interrupted()

    Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. ..."

    I think it's better to use a custom property for any meaningful thread statuses. Of course, this usually means some kind of common base class or interface for threads, which is also not a great solution.

    ReplyDelete
  7. Villane,

    it's true that the Thread.interrupt() is not really reliable, because its not well defined how to use it. But it is the *only* way to terminate a blocking call..

    Michael

    ReplyDelete
  8. Hello,

    I find this discussion very useful. I have coded a garbage collector which runs in a separate thread and removes objects from a cache. The code is as follows:

    public void run(){

    while (true){
    try{
    Thread.sleep(SOME_DURATION);
    cache.lock.writeLock().lock();
    //clean up the cache
    cache.lock.writeLock().unlock();
    }
    catch(InterruptedException ie){
    }
    }//while
    }

    I think I am okay with not adding the Thread.currentThread().interrupt() in the catch block because I don't want the garbage collector to be turned off during program execution. I wonder though if the thread could ever be interrupted by some process that has been asked to terminate the thread...for example a program from which you can gracefully shut down a running application. You would not know the source of the InterruptedException. If the code above was interrupted by a program which wants to shut down the thread, then the while loop should be terminated. If some action in the loop caused the interrupt, then the loop should continue, and be given a chance to repeat the action at a later time.

    If possible, please let me know the possible sources which would invoke the interrupt and if my concerns are valid.

    Thanks so much.

    -Paula

    ReplyDelete
  9. Paula,
    if you create the thread and you have control over the thread, then you can swallow the exception. You have somehow to define your own mechanism to shut down the thread. If you want to stop the Thread, while it is sleeping for SOME_DURATION, you'd have to call the method Thread.interrupt(). But if you swallow the interrupt you won't get out of your infinite while loop. If you use the interrupt state of your thread as mechanism to shut it down your loop would look like:

    while(!isInterrupted()) {
    try {
    Thread.sleep(SOME_DURATION);
    //clean up the cache
    } catch(InterruptedException ie){
    break;
    }
    }


    But then you should make sure that no code that you call from within the loop is swallowing the interrupt exception. And that is really the problem. Because there is so much code out there that swallows InterruptedException, using the thread interrupt mechanism is not really reliable....


    Michael

    ReplyDelete
  10. hello every body.
    I would like to know how i could stop my threads with a boolean .

    ReplyDelete
  11. public class myThread implements Runnable{

    private Thread T1;

    public void Start ( ) {
    myThread = new Thread( this );
    myThread.start();
    }
    public void run(){
    try{
    for (int i=0; i<someThing; i++){
    traitement();
    Thread.sleep(1000);
    }//end for
    catch(InterruptedException e){}
    }//end try
    }//end run

    // and this my method to stop threads but i can't stop it. NEED HELP.

    boolean finish = true;
    synchronise public void stopThread(){
    finish = true;
    while(finish){
    if (T1.isAlive()){
    T1.interrupt();
    T1 = null;
    }
    }

    }
    }

    ReplyDelete
  12. Does this whole article has the assumption that interruption is a valid way to terminate a thread? What if I want my thread to be *uninterruptable*? If I'm the owner of the thread, it's my right to not let anyone outside interrupt it.

    In this case I believe it's perfectly fine to at *most* log this exception. Yes I'm being rude to outside code that wants to interrupt my thread, but if you don't read my javadoc that says enqueuing a "stop" object is the only accepted way to stop my thread, it's your fault, not mine.

    ReplyDelete
  13. InterrupteException is a checked exception and many a times it litter the code, would have been really good if it was RuntimeException, does anyone knows why its not a Runtime Exception ?

    Javin
    Why wait() and notify() method must be called from synchronized context

    ReplyDelete
  14. Thanks another good video,

    The producer–consumer problem (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, who share a common, fixed-size buffer used as a queue
    http://www.youtube.com/watch?v=dUwboVZ59KM

    Learn when and How to Stop the Thread,using jconsole or JvisualVM to indetify is the thread is running
    http://www.youtube.com/watch?v=3_Bqhw0d2ko

    http://www.youtube.com/watch?v=3E3gNReWCfM
    Just purchasing lens is waste of money until you justify the reason behind it,lenses are costly, and prime lens are even costlier, choose wisely the lens you are looking for is really needfull, read the articles blog's gather information about it

    ReplyDelete