5

I am implementing an interface which throws IOException. In my implementation, I call another method which can block, and therefore throw InterruptedException.

Context:

  • I want to end the treatment if I am interrupted;
  • this is not a thread I created myself.

My current idea is to do as such (skeleton code):

@Override
public void implementedMethod()
    throws IOException
{
    try {
        methodThatBlocks();
    } catch (InterruptedException ignored) {
        Thread.currentThread().interrupt();
        throw new IOException();
    }
}

is that the correct way? Or should I just throw and not .interrupt()?

fge
  • 119,121
  • 33
  • 254
  • 329
  • 1
    Don't call `interrupt()`. If you've caught an `InterruptedException`, then your thread was already interrupted. – Dawood ibn Kareem Mar 24 '14 at 20:50
  • 3
    @DavidWallace uhwait, I'm confused; I thought that if you received this exception the thread interrupt status was cleared – fge Mar 24 '14 at 20:53
  • @fge right, it was cleared. But why do you want to set it again? – Dawood ibn Kareem Mar 24 '14 at 21:07
  • Well, this is not code which runs in a thread which I create myself; I believe this piece of context matters, so I'll edit the question and add that – fge Mar 24 '14 at 21:12
  • @fge Actually, I had a tough bug once, stemming from the fact that ActiveMQ did not restore the interrupted flag. This eventually caused threads to be left hanging and the application unable to regularly shut down. – Marko Topolnik Mar 24 '14 at 21:17
  • @MarkoTopolnik so basically, don't take risks and let the caller handle that? – fge Mar 24 '14 at 21:27
  • I would definitely call interrupt(), to reset the interrupt status that has been cleared by the InterruptedException. You want code calling your method to be able to know that the thread has been interrupted, and thus do all it can to stop the thread execution ASAP. – JB Nizet Mar 24 '14 at 22:05
  • 1
    @DavidWallace In general, it's important to reassert the interrupted status so that callers receive notification of the interruption. The crux of the question here, as I understand it, is whether it's necessary in the context of a checked exception that isn't `InterruptedException`. (I would say it's not necessary if raising `InterruptedException`.) – erickson Mar 24 '14 at 22:22
  • @DavidWallace [Here's a good explanation](http://www.ibm.com/developerworks/library/j-jtp05236/#2.0) of the principle. – erickson Mar 24 '14 at 22:28

2 Answers2

4

Yes, you should call interrupt() to let the calling code know that the thread has been interrupted. If you don't do it, since the InterruptedException clears it, the calling code will have no way to know about the interruption and won't stop running although it should.

Let me quote Java Concurrency in Practice:

Restore the interrupt. Sometimes you cannot throw InterruptedException, for instance when your code is part of a Runnable. In these situations, you must catch InterruptedException and restore the interrupted status by calling interrupt on the current thread, so that code higher up the call stack can see that an interrupt was issued, as demonstrated in Listing 5.10.

public class TaskRunnable implements Runnable {
    BlockingQueue<Task> queue;
    ...
    public void run() {
        try {
            processTask(queue.take());
        } catch (InterruptedException e) {
             // restore interrupted status
             Thread.currentThread().interrupt();
        } 
    }
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Of course not. The thread is already unblocked and running. In the code that is about to throw an exception. What would be the point?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Even though this is not "my" thread? How will that behave if the immediate caller ignores the `IOException` and merrily goes its way? – fge Mar 24 '14 at 22:21
  • Care to elaborate? You have a thread. You want it to stop. So you ask it to interrupt itself by calling interrupt(). That causes an InterrupedException to be thrown by the blocking method, which also clears the interrupt status. Now you want to signal the calling code that the thread has been interruped and should thus stop running. And you can't throw an InterruptedException. How would you do, except by setting the interrupt status. – JB Nizet Mar 24 '14 at 22:21