如果我有一个带有try / finally部分的函数,并且运行它的线程在try块中被中断,那么finally块是否会在中断实际发生之前执行?
答案 0 :(得分:8)
According to the Java Tutorials,"如果执行try
或catch
代码的线程被中断或终止,finally
块可能无法执行,即使应用程序为一个整体继续。"
这里有完整的段落:
当
finally
块退出时,try
块始终执行。这个 确保即使出现意外情况也会执行finally
块 异常发生。但finally
不仅仅对例外有用 处理 - 它允许程序员避免使用清理代码 被return
,continue
或break
意外绕过。进行清理finally
块中的代码始终是一个好习惯,即使没有 预计有例外。注意:如果在执行
try
或catch
代码时JVM退出,则finally
块可能无法执行。同样,如果线程正在执行try
或catch
代码被中断或终止,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();
打印 - 最后执行
答案 1 :(得分:4)
Java中的线程中断只是设置一个标志。它不会对当前正在执行的代码造成任何特殊情况,或影响控制流。
如果你的线程参与或试图进入抛出InterruptedException的操作,则从调用该方法的点抛出异常,如果它在try块内,则finally将在异常离开之前执行就像平常一样。
答案 2 :(得分:4)
Oracle的许多Java教程都很有帮助(我的答案引用了受保护的块页面和SAX介绍),但它们不一定是权威的,有些错误或不完整。问题中引用的引用将中断与JVM退出混淆,这令人困惑。
首先,Java中的线程中断与OS级别的中断无关。 Sharing a name creates opportunities for confusion but there is no connection
接下来,JVM退出显然会杀死线程而没有机会进行任何清理。如果进程在线程到达finally块之前就已经死了,那就太糟糕了。但是没有比较中断。关于中断的任何事情都无法阻止最终的阻止。
中断的设计原则是作用于中断需要被中断的线程的协作。线程中断响应自行决定,中断不会强制线程做任何事情。所有调用Thread#interrupt()都会在线程上设置一个标志。阻止等待或睡眠的方法检查标志,看看它们是否应该提早醒来。 (InterruptedException是一个经过检查的异常,因此您可以告诉谁在什么时候抛出它,并且您的Runnable可以为它进行规划。)此外,任何代码都可以使用Thread#isInterrupted()来检查其线程是否已设置标记。
当Thread#sleep()识别出设置了中断标志时,它会在抛出InterruptedException之前清除该标志。当你的线程捕获InterruptedException时,使用Thread.currentThread()。interrupt()恢复标志是很好的方式,以防万一在该线程中运行任何需要了解中断的其他代码。当你有更复杂的嵌套同步器情况时会发挥作用,例如,某些深度嵌套的组件可能会使其睡眠中断,让它保持清除可能会阻止更高层知道中断。在一个简单的玩具示例中,如此处的其他答案中的那些,如果标志是否恢复并不重要,则不会再次检查它并且线程终止。
答案 3 :(得分:3)
在comments到answer,@ Risadinha询问了一个非常有效的问题,即如果我们通过调用恢复finally
块内的中断标志,catch
块中的代码是否会被执行Thread.currentThread().interrupt()
。
以下是要测试的小代码段:
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;
}
答案 4 :(得分:1)
中断的效果是在下次发生阻塞操作时抛出InterruptedException
(实际上,下次调用方法时指定它可以抛出InterruptedException
),此时 - 像往常一样 - 遵循正常的try/catch
执行流程,它确实在finally
和任何适用的try
之后执行catch
阻止。
答案 5 :(得分:0)
它将以与try块中的任何其他异常相同的方式执行,而不是在中断之前执行。