public class ADaemon implements Runnable {
@Override
public void run() {
try {
System.out.println("Starting ADaemon");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("Exiting via InterruptedException");
} finally {
System.out.println("This should always run?");
}
}
public static void main(String... args) {
Thread t = new Thread(new ADaemon());
t.setDaemon(true);
t.start();
}}
结果
Starting ADaemon
Exiting via InterruptedException
This should always run?
我尝试使用“ Thinking in Java”第4版中的代码示例,但没有得到书中所述的结果,finally块仍在执行,为什么会这样?顺便说一句,我正在使用oracle jdk 10.0.1。
-------------更新----------
我的maven-runner插件似乎正在运行某些东西,我禁用了它,并且得到的效果与书中所述相同。
答案 0 :(得分:3)
您说这本书说:
“可能无法执行 finally块” 。
(添加了强调。)
那不是说:
“将不会执行finally块 ” 。
我认为这本书暗示着,当应用程序退出时,守护进程线程是否会获得中断(或某种中断),这是未指定的(可能还特定于JVM)。
当然,如果守护程序线程按如下所示捕获并忽略了“中断的”异常,那么我会期望:finally
永远不会执行。
public class ADaemon implements Runnable {
@Override
public void run() {
try {
System.out.println("Starting ADaemon");
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("Caught InterruptedException");
}
}
} finally {
System.out.println("This should always run?");
}
}
public static void main(String... args) {
Thread t = new Thread(new ADaemon());
t.setDaemon(true);
t.start();
}
}
如果守护线程未执行可中断代码,我会期望类似的行为。
答案 1 :(得分:2)
这应该总是运行吗? 是。除非JVM实际停止,否则将{strong>保证输入该块finally
。
System.exit(-1);
catch
块中的可以防止这种情况。 如果是您想要的。它还将停止JVM!这本书警告您,如果所有其他线程都已完成,则可能永远不会在JVM终止之前调度守护程序线程。您正在直接致电start()
。考虑使用
SwingUtilities.invokeLater(t);
除非您删除t.setDaemon(true);
答案 2 :(得分:0)
finally块是一个功能强大的工具(如果使用不当,将会很危险),它会在try或catch块完成后(尽管上面突出显示了一些小情况)几乎总是运行。 看这个例子:
try{
throw new Exception();
}catch(Exception e){
return;
}finally{
System.out.println("Shouldn't run?");
}
如果这是在方法中,则将执行finally块 still (切勿执行此操作,因为这是一种不好的做法)。尽管您执行了诸如关闭流之类的操作,但它仍然可以执行任何清除操作(现在可以通过语句“ try”中的括号自动完成此操作)。