23

If I have a function with a try/finally section, and the thread running it is interrupted while in the try block, will the finally block execute before the interruption actually occurs?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
user940016
  • 2,878
  • 7
  • 35
  • 56
  • 1
    http://stackoverflow.com/questions/4371560/what-happens-when-you-invoke-a-threads-interrupt – Santosh Jan 29 '13 at 06:17
  • You should clear up what you mean by 'interrupted' - this word is overloaded :( It means different things to firmware/driver developers, OS developers and java developers. – Martin James Jan 29 '13 at 09:10
  • 2
    Well, I tagged the question as "java", and I mentioned try/finally, so I figured one can understand that I'm talking about interrupting threads in Java... – user940016 Jan 29 '13 at 12:25

6 Answers6

13

According to the Java Tutorials, "if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues."

Here's the full passage:

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

class Thread1 implements Runnable {

    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally executed");
        }
    }
}

...

t1.start();
t1.interrupt();

It prints - finally executed

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
  • 4
    Hmm... I can understand finally not getting executed if the thread is killed. However, the thread being interrupted should *NOT* stop the finally clause from being executed. I'm not sure why this passage says that. Here's the JLS description in its full glory: http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2 – sjlee Jan 29 '13 at 16:34
  • @sjlee - Thanks for comment, I have tested in code. Its working as I said. – Subhrajyoti Majumder Jan 29 '13 at 17:27
  • 5
    OK, you mean that finally **DOES** get executed even if the thread is interrupted, correct? If so, your answer needs to be clarified. It sounds as though finally may not execute if the thread is interrupted. – sjlee Jan 29 '13 at 19:07
  • 1
    One had assumed it is referring to the native thread to which the java thread is bound being interrupted at the system level, not a java thread interrupt. – Affe Jan 29 '13 at 22:27
  • 7
    Actually, it only works because the Interruption is catched. You are not properly handling the InterruptedException as you are simply swallowing it. You should propagate it either by re-throwing or by calling Thread.currentThread.interrupt(). For more information, see http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html . The question then is - will the finally still be executed? – Risadinha Oct 10 '13 at 16:57
  • @Risadinha, here is the answer to the question you raised: http://stackoverflow.com/a/33436444/3050466. Great question BTW! – Keenle Oct 30 '15 at 12:53
  • 1
    @Risadinha: restoring the interrupt flag cannot keep the finally block from getting executed here. It would only affect whether any other code run by this thread can detect whether the thread has been interrupted. Not having it doesn't affect the validity of Subhrajyoti's test. – Nathan Hughes Oct 30 '15 at 13:30
5

In the comments to the answer, @Risadinha asked very valid question about whether code in finally block gets executed if we restore interruption flag inside catch block by calling Thread.currentThread().interrupt().

Here is small code snippet to test:

final SomeContext context = new SomeContext();
Thread thread = new Thread() {
    @Override
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // this code gets executed even though
            // we interrupt thread in catch block.
            context.value = 9;  
        }
    }
};

thread.start();
thread.interrupt();

thread.join(); // need to wait for thread code to complete

assertEquals(context.value, 9); // values are the same!

SomeContext class code:

class SomeContext {
    public volatile int value = 10;
}
Community
  • 1
  • 1
Keenle
  • 12,010
  • 3
  • 37
  • 46
  • 2
    Thanks for this test. Though, I'd still not put any mission critical code in the finally block, seeing that the Java Tutorials state that there is no guarantee that it will execute if the the thread is interrupted or killed. Might depend on the JVM/Vendor/Version and/or resources etc. – Risadinha Oct 30 '15 at 13:14
5

Many of Oracle's Java tutorials are helpful (I have answers referencing the guarded blocks page and the SAX introduction), but they are not necessarily authoritative, and some of them have mistakes or are incomplete. The quote referenced in the question conflates interruption with the JVM exiting, which is confusing.

First, thread interruption in Java has nothing to do with OS-level interrupts. Sharing a name creates opportunities for confusion but there is no connection.

Next, JVM exit obviously kills the thread without an opportunity to do any cleanup. If the process dies before the thread has gotten as far as the finally block, too bad. But there's no comparison to interruption. Nothing about interruption prevents finally blocks from completing.

A design principle of interruption is that acting on the interruption requires the cooperation of the thread being interrupted. The thread interrupted responds at its discretion, the interruption doesn't compel the thread to do anything. All calling Thread#interrupt() does is set a flag on the thread. Blocking methods like wait or sleep check the flag to see if they should wake up early. (InterruptedException is a checked exception so you can tell who throws it when, and your Runnable can plan for it.) Also any code can use Thread#isInterrupted() to check whether its thread has had the flag set.

When Thread#sleep() recognizes the interrupted flag is set, it clears the flag before throwing InterruptedException. When your thread catches an InterruptedException it's good manners to restore the flag using Thread.currentThread().interrupt(), just in case there is any other code running in that thread that needs to know about the interruption. This comes into play when you have more complex situations with nested synchronizers where, for instance, some deeply nested component could get its sleep interrupted, letting it stay cleared could prevent higher layers from knowing about the interruption. In a simple toy example like the ones in other answers here, it doesn't matter if the flag is restored or not, nothing checks it again and the thread terminates.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • @Joe: from reading a lot of books, like Java Concurrency in Practice, and from trying these things out for myself. Was there something in particular where you wanted to know where it came from? – Nathan Hughes Aug 18 '17 at 01:10
4

A Thread Interrupt in Java is just setting a flag. It doesn't cause anything special to happen to currently executing code, or affect the flow of control.

If your thread is engaged in, or attempts to enter, an operation that throws InterruptedException, then the exception is thrown from the point where that method is invoked and if it's inside a try block, the finally will execute before the exception leaves just like normal.

Affe
  • 47,174
  • 11
  • 83
  • 83
  • @Joe how does one 'controlling' thread cause another thread to be 'terminated' within the scope of the question, being things you can do within the java language? Even the deprecated and much maligned thread.stop will cause the stopped thread to enter a finally block. – Affe Aug 17 '17 at 23:23
2

The effect of interruption is to throw an InterruptedException the next time a blocking operation occurs (in practice, the next time a method is called that specifies it can throw an InterruptedException), at which point -- as usual -- the normal try/catch execution flow is followed, which does indeed execute the finally block after the try and any applicable catches.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
0

It will execute the same way as with any other exception from the try block, not before the interruption.

jdb
  • 4,419
  • 21
  • 21