我有一个定义良好的Try/Catch/Finally链的应用程序,它在正常情况下退出并执行finally块,但是当某人过早地在GUI中命中红色X时,程序完全存在(代码= 0),并且主线程的最终块不被调用。
事实上,我确实希望程序在单击red-X时退出,但我不想跳过最后的{}块!我在GUI中手动插入了finally块中最重要的部分,但我真的不想这样做,因为我希望GUI与实际程序解耦:
class GUI { // ...
...
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
try {
processObject.getIndicatorFileStream().close();
} catch (Exception ignore) {}
System.exit(0);
}
});
...
}但我宁愿打个这样的电话:
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);并确保在退出后从每个线程调用所有最后的{}块。
我知道这是意料之中的。如果应用程序是从单独的线程(例如GUI线程)关闭的,那么主线程就会停止运行。
简而言之, --如何确保System.exit(0)或JFrame.EXIT_ON_CLOSE仍然会导致每个线程的最后块执行?
发布于 2013-07-22 16:43:01
如果您没有其他的设计更改选择,那么您可能需要一个JVM关机挂钩,当System.exit被调用时,可以添加它来运行一段代码。
关机挂钩是一种特殊的构造,允许开发人员在JVM关闭时插入要执行的代码。在我们需要进行特殊清理操作以防止VM关闭的情况下,这是很有用的。
您可以添加关闭钩子,如下所述:
Runtime.getRuntime().addShutdownHook(Thread)在这里阅读更多关于关机挂钩的信息:
http://java.dzone.com/articles/know-jvm-series-2-shutdown
警告词:
我们必须记住的是,不能保证关闭钩子将始终运行。如果JVM由于某些内部错误而崩溃,那么它可能会崩溃而没有机会执行一条指令。另外,如果O/S给出了一个SIGKILL (http://en.wikipedia.org/wiki/SIGKILL)信号(Unix/Linux中的TerminateProcess -9 )或TerminateProcess(TerminateProcess),那么应用程序就必须立即终止,而无需等待任何清理活动。除了上述之外,还可以终止JVM,而不允许通过调用Runime.halt()方法运行关机挂钩。
发布于 2013-07-22 17:00:04
如果您碰巧有这样的线程,这些线程可以在任何时候、在它们的循环中的任何点、在它们调用的任何方法内的任何点上合法地停止,我想警告您,您不太可能这样做,那么您可以在程序退出时将它们全部关闭。这将导致在每个线程中抛出异常,finally块将执行。
然而,实现您的目标并使GUI与程序逻辑分离的正确方法是从GUI发出一个“退出”信号,这将触发所有应用程序清理,这是在一个完全不同的类中编写的。如果您有正在运行的线程,那么在每个线程中实现interrupt机制。
实现退出信号的方法有很多。例如,您的业务代码可以为一个特殊事件注册GUI侦听器,这将触发清理。您还可以在await上有一个线程,它只执行CountDownLatch上的任何事情,这将是GUI中的countDown。
请不要以任何代价使用关闭钩子。这是可以想象到的最肮脏的机制,只有在所有正常的清理程序都失败时,这才是最后的手段。它永远不会被用作常规关机程序的一部分。
总之,没有清理应用程序关闭的绝好方法。您必须为每个特定的关注点实现特定的机制。
发布于 2017-03-05 11:19:17
使用现代的Java,在所有应用程序窗口上的Window.dispose()可以提供比System.exit(0)更优雅的退出AWT应用程序的可能性,请参见
https://docs.oracle.com/javase/8/docs/api/java/awt/Window.html#dispose--
/** Listens and closes AWT windows.
* The class is implemented as singleton since only one is needed.
*/
public class ExitListener extends WindowAdapter {
/** the instance object */
private static final ExitListener INSTANCE = new ExitListener();
// hide the constructor
private ExitListener () {}
/** retrieve the listener object */
public static ExitListener getInstance () {
return INSTANCE;
}
@Override
public void windowClosing ( final WindowEvent e ) {
e.getWindow().dispose();
}
}用你的窗户
window.addWindowListener( ExitListener.getInstance() );然而,在不利的环境中要小心,见:
https://docs.oracle.com/javase/8/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
https://stackoverflow.com/questions/17792939
复制相似问题