我有以下
public static void main(String[] args) {
boolean running = true;
boolean foo= false;
while(running)
{
doSomeTask(); // might set foo true
if(foo) {
//This call waits/blocks until gui is done working.
fireUpSwingGui(); //does work...
foo=false;
godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft();
}
}
}
希望godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft()
说明一切。
请记住,当foo
在true
内某处doSomeTask()
再次变为{{1}}时,我们可能会在以后再次启动gui。
答案 0 :(得分:6)
查看AWT Threading Issues,它解释了退出AWT应用程序的标准。您要关注的部分如下:
因此,一个希望彻底退出的独立AWT应用程序 不调用System.exit必须:
- 确保应用程序完成后,所有AWT或Swing组件都不可显示。这可以通过在所有顶级Windows上调用Window.dispose来完成。见Frame.getFrames。
- 确保应用程序使用任何AWT或Swing组件注册的AWT事件侦听器的任何方法都无法运行到无限循环或无限期挂起。例如,由某些AWT事件触发的AWT侦听器方法可以将相同类型的新AWT事件发布到EventQueue。参数是AWT事件侦听器的方法通常在辅助线程上执行。
快速示例应用以展示......
import java.awt.Frame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class CloseAWT
{
private static boolean running = true;
private static int response = -1;
public static void main(String[] args)
{
boolean showSwing = true;
boolean checkFrames = true;
while (running)
{
if (showSwing)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
response = JOptionPane.showConfirmDialog(null, "Hello World?");
}
});
showSwing = false;
}
else
{
if (response >= 0 && checkFrames)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// topFrame.dispose();
Frame[] frames = Frame.getFrames();
System.out.printf("frames.length=%d\n", frames.length);
}
});
checkFrames = false;
}
}
}
}
}
为了确认行为符合预期,我在JProfiler中运行了这个。单击“是”以关闭确认对话框后,'AWT-EventQueue-0'线程被标记为已死。在此之后唯一活着的线程是'main'和侦听Ctrl-Break的线程。
我强烈建议您使用JProfiler,YourKit,JProbe或其中一个免费的分析器,以确保您已正确释放所有组件并删除所有侦听器。< / p>
最后一个想法......您可能想要考虑将GUI作为一个单独的进程生成,并使用某种IPC在您的守护程序进程和GUI之间传递信息。虽然这会产生额外进程和IPC的额外开销,但它可以让您更好地确保在不再需要时完全清理GUI。
答案 1 :(得分:1)
假设您正在打开JFrame
个问题,为什么不将它们存储在一个集合中,并在godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft()
内部迭代它们并调用setVisible(false);
我不确定你是否真的可以停止驱动gui的AWT事件队列。