如果运行该函数的线程被中断,finally块是否会执行?

如果我有一个带有try / finally部分的函数,并且运行它的线程在try块中被中断,那么finally块是否会在中断实际发生之前执行?

根据Java Tutorials ,“如果执行trycatch代码的线程被中断或finally即使整个应用程序继续执行, finally块也可能无法执行。”

这是完整的段落:

try块退出时, finally总是执行。 这确保即使发生意外exception也会执行finally块。 但finally不仅仅是exception处理有用 – 它允许程序员避免因returncontinuebreak意外绕过清理代码。 将清理代码放在finally块中总是一种很好的做法,即使没有预期的例外情况也是如此。

注意:如果在执行trycatch代码时JVM退出,则finally块可能无法执行。 同样,如果执行trycatch代码的线程被中断或finally ,则即使应用程序作为一个整体继续, finally块也可能不会执行。

 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(); 

它打印 – 最后执行

Java中的线程中断只是设置一个标志。 它不会对当前正在执行的代码造成任何特殊情况,或影响控制流。

如果你的线程参与或试图进入一个抛出InterruptedException的操作,那么从调用该方法的点抛出exception,如果它在try块内,则finally将在exception离开之前执行,就像正常一样。

Oracle的许多Java教程都很有帮助(我的答案引用了受保护的块页面和SAX介绍),但它们不一定是权威的,有些错误或不完整。 问题中引用的引用将中断与JVM退出混淆,这令人困惑。

首先,Java中的线程中断与OS级别的中断无关。 共享名称会产生混淆的机会,但没有联系 。

接下来,JVM退出显然会杀死线程而没有机会进行任何清理。 如果进程在线程到达finally块之前就已经死了,那就太糟糕了。 但是没有比较中断。 关于中断没有任何阻止最终阻止完成。

中断的设计原则是作用于中断需要被中断的线程的协作。 线程中断响应自行决定,中断不会强制线程做任何事情。 所有调用Thread#interrupt()都会在线程上设置一个标志。 阻止等待或睡眠的方法检查标志,看看它们是否应该提早醒来。 (InterruptedException是一个已检查的exception,因此您可以告诉谁何时抛出它,并且您的Runnable可以为它进行规划。)此外,任何代码都可以使用Thread#isInterrupted()来检查其线程是否已设置标志。

当Thread#sleep()识别出设置了中断标志时,它会在抛出InterruptedException之前清除该标志。 当你的线程捕获InterruptedException时,使用Thread.currentThread()。interrupt()恢复标志是很好的方法,以防万一在该线程中运行任何需要知道中断的其他代码。 当你有更复杂的嵌套同步器情况时会发挥作用,例如,一些深层嵌套的组件可能会使其睡眠中断,让它保持清除可以防止更高层知道中断。 在一个简单的玩具示例中,如此处其他答案中的那些,如果标志是否已恢复无关紧要,则不会再次检查它并且线程终止。

在回答的评论中,@ Risadinha问了一个非常有效的问题,即如果我们通过调用Thread.currentThread().interrupt()恢复catch块中的中断标志,是否会执行finally块中的代码。

以下是要测试的小代码段:

 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 SomeContext { public volatile int value = 10; } 

中断的影响是在下次发生阻塞操作时抛出InterruptedException (实际上,下次调用一个方法时指定它可以抛出InterruptedException ),此时 – 正常情况下 – 正常的try/catch遵循执行流程,它确实在try和任何适用的catch es之后执行finally块。

它将以与try块中的任何其他exception相同的方式执行,而不是在中断之前执行。