典型的 Swing 应用程序在开始时启动 EDT,当最后一个窗口关闭时,应用程序基本上以 System.exit 隐式或显式停止。
但我的小应用程序实际上是一个框架插件,它对 Swing 一无所知。我的插件在调用时会显示一个对话框,以便从用户那里获得一些输入并在之后退出,但框架将/必须继续运行。所以我不能打电话System.exit。
但是,如果我不这样做,EDT 将继续运行,一旦框架完成,EDT 仍将运行并运行并运行......
所以我想在不杀死应用程序的情况下杀死 EDT。我怎么做?
典型的 Swing 应用程序在开始时启动 EDT,当最后一个窗口关闭时,应用程序基本上以 System.exit 隐式或显式停止。
但我的小应用程序实际上是一个框架插件,它对 Swing 一无所知。我的插件在调用时会显示一个对话框,以便从用户那里获得一些输入并在之后退出,但框架将/必须继续运行。所以我不能打电话System.exit。
但是,如果我不这样做,EDT 将继续运行,一旦框架完成,EDT 仍将运行并运行并运行......
所以我想在不杀死应用程序的情况下杀死 EDT。我怎么做?
Oracle/Sun 的以下文档阐明了这个问题:AWT 线程问题
[...]
在 1.4 之前,辅助线程永远不会终止。
从 1.4 开始,由于 4030718 的修复,行为发生了变化。在当前实现中,AWT 终止其所有帮助线程,从而允许应用程序在以下三个条件为真时干净地退出:
- 没有可显示的 AWT 或 Swing 组件。
- 本机事件队列中没有本机事件。
- java EventQueues 中没有 AWT 事件。
因此,希望在不调用 System.exit 的情况下干净退出的独立 AWT 应用程序必须:
- 确保应用程序完成时所有 AWT 或 Swing 组件都无法显示。这可以通过在所有顶级 Windows 上调用 Window.dispose 来完成。请参阅 Frame.getFrames。...
- 确保应用程序向任何 AWT 或 Swing 组件注册的 AWT 事件侦听器的任何方法都不会陷入无限循环或无限期挂起。例如,某个 AWT 事件触发的 AWT 侦听器方法可以将一个新的相同类型的 AWT 事件发布到 EventQueue。论据是 AWT 事件侦听器的方法通常在辅助线程上执行。
[...]
可能有一些隐藏的窗口(例如,显示的对话框JOptionPane.showMessageDialog(…)已经关闭)阻止 Swing 退出。您可以使用
Stream.of(Window.getWindows()).forEach(System.out::println);
如果您不再需要它们,您可以轻松地摆脱它们:
Stream.of(Window.getWindows()).forEach(Window::dispose);
然后事件调度线程应该停止。