Java 停止所有Awt/Swing线程和监视器等,以便只剩下主线程

Java 停止所有Awt/Swing线程和监视器等,以便只剩下主线程,java,multithreading,swing,awt,Java,Multithreading,Swing,Awt,我有以下几点 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

我有以下几点

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();
        }
    }
}
希望
godmodelereasegui和所有资源都能满足mainthreadleft()
的所有需求


请记住,当
foo
再次变为
true
时,我们可能会在
doSomeTask()

中的某个地方再次启动gui。假设您正在打开
JFrame
iInstances,为什么不将它们存储在一个集合中,并存储在
godmodelereaseGUI和所有资源中
您对它们进行迭代,并调用
setVisible(false)

我不确定您是否真的可以停止驱动gui的AWT事件队列。

请看一看,它解释了AWT应用程序退出的条件。您希望重点关注的部分如下:

因此,希望干净地退出的独立AWT应用程序 不调用System.exit必须:

  • 确保应用程序完成后,所有AWT或Swing组件都不可显示。这可以通过调用所有顶级窗口来实现。看
  • 确保应用程序使用任何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的线程

我强烈建议您使用类似、或其中一个免费的探查器来确保您已经正确地发布了所有组件并删除了所有侦听器


最后一个想法。。。您可能需要考虑将您的GUI生成为单独的进程,并使用某种类型的IPC在守护进程和GUI之间传递信息。尽管这会增加额外进程和IPC的额外开销,但它将为您提供更大的保证,即当不再需要GUI时,它将被完全清理。

Jason,我最终以不同的方式解决了这个问题,但这是一个很好的答案,我会将其标记为正确。我最终在我的应用程序中使用了一个JavaShell框架,它基本上是从我的应用程序中执行应用程序,并处理完之后优雅地关闭它的所有细节。看一看我在那里找到的代码,它基本上(就我所见)实现了您在这里描述的功能。