java 应用程序 gui
最近,我遇到了一个或两个Java GUI应用程序在关闭时无法关闭的问题。 他们似乎是一个过程,消耗着计算机资源。 今天,我深入探究了问题的根源,这是一个我以前不曾意识到的棘手陷阱,所以我想我会分享一下。
理论上,当您关闭Java应用程序时,应停止所有线程,并且进程应终止。 就我而言,当我监视应用程序时,我希望完成的线程(例如,Swing工作池)仍处于活动状态(奇怪)。 原来的原因是AWT Shutdown线程没有终止所有帮助程序线程,其原因是EventQueues中仍然存在AWT事件。 我将解释其原因是真正的偷偷摸摸的小gatcha。
我的应用程序使用了一个具有常规睡眠的线程,但是当醒来时会进行一些计算,然后调用以更新gui:
Thread updateThread = new Thread(new Runnable() {@Override
public void run() {int i = 0;do {try {Thread.sleep(300); // 300msgui.updateValue(SOME_VALUE)} catch(InterruptException ex) {return;} frame.setValue(SOMEDATA); } while(i++ < 100); } }, "updateThread");updateThread.setDaemon(true);
updateThread.start();
现在您将注意到,如果线程被中断并且作为守护程序线程启动,则该线程返回。 我以为,作为应用程序关闭的一部分,线程将被终止,但实际上并非如此。 这是由gui.updateValue(SOME_VALUE)使用InvokeLater引起的:
public void updateValue(final int value) {// make sure we access graphics in the EDT threadjava.awt.EventQueue.invokeLater(new Runnable() {@Override public void run() { try { ......... SOME CODE }catch(Exception t) {// not a lot to do } } });
}
InvokeLater基本上是在EventQueue上放置一个事件,因此AWT Shutdown线程想要关闭应用程序。 AWT Shutdown线程每秒钟检查一次EventQueues,但是正如您将看到的,我的线程会执行亚秒级更新(300毫秒),因此队列上始终有一个事件! 简而言之,AWT Shutdown线程永远不会终止我希望其终止的线程,因此需要终止应用程序。
在我的线程的while循环中,变通方法很简单,我还检查了通过它进行更新的JComonent是否仍然可见并显示,如果不是退出循环,则该线程死亡,因此没有其他事件放在事件线程上,然后应用程序按预期关闭:)
Thread updateThread = new Thread(new Runnable() {@Override
public void run() {int i = 0; do { try { Thread.sleep(300); // 300msgui.updateValue(SOME_VALUE); }catch(InterruptException ex) { return;} frame.setValue(SOMEDATA);}while(i < 100 && progressGlassPane.isVisible() && progressGlassPane.isShowing());}
}, "updateThread");
updateThread.setDaemon(true);
updateThread.start();
因此,简而言之,不要以低于一秒的频率从帮助程序线程中调用InvokeLater,除非在正在更新的组件不再可见的情况下也终止了该线程!
作为旁注,发现问题后,我发现这非常
参考: Coal Face博客上Java桌面开发的 JCG合作伙伴 Steve Webb的Java GUI Application Shutdown Gotcha 。
翻译自: https://www.javacodegeeks.com/2012/05/java-gui-application-shutdown-gotcha.html
java 应用程序 gui