Does the finally block execute if the thread running the function is interrupted?

后端 未结 6 1126
执笔经年
执笔经年 2020-12-17 09:01

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 actu

相关标签:
6条回答
  • 2020-12-17 09:48

    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.

    0 讨论(0)
  • 2020-12-17 09:52

    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.

    0 讨论(0)
  • 2020-12-17 09:55

    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;
    }
    
    0 讨论(0)
  • 2020-12-17 10:01

    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

    0 讨论(0)
  • 2020-12-17 10:04

    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.

    0 讨论(0)
  • 2020-12-17 10:06

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

    0 讨论(0)
提交回复
热议问题