如果你在 Swing 中打开一个对话框,例如 JFileChooser,它有点像下面的伪代码:
摆动事件线程{ 创建对话框 将侦听器添加到对话框关闭事件 { returnValue = somethingFromDialog } 显示对话框 (等到它关闭) 返回返回值 }
我的问题是:这怎么可能起作用?如您所见,线程等待返回,直到对话框关闭。这意味着 Swing 事件线程被阻塞。然而,可以与对话框交互,AFAIK 需要此线程运行。
那么这是如何工作的呢?
如果你在 Swing 中打开一个对话框,例如 JFileChooser,它有点像下面的伪代码:
摆动事件线程{ 创建对话框 将侦听器添加到对话框关闭事件 { returnValue = somethingFromDialog } 显示对话框 (等到它关闭) 返回返回值 }
我的问题是:这怎么可能起作用?如您所见,线程等待返回,直到对话框关闭。这意味着 Swing 事件线程被阻塞。然而,可以与对话框交互,AFAIK 需要此线程运行。
那么这是如何工作的呢?
现有的事件调度线程被阻塞,因此 swing 创建另一个线程来泵送事件。这就是对话期间的事件分派线程。
Swing 创建了一个单独的本机线程来抽取本机操作系统窗口消息。这与 AWT 事件线程是分开的。
在 Windows 上,您会看到这些线程
"AWT-Windows" - the native UI thread
"AWT-EventQueue-0" - the current AWT event dispatch thread
编辑:反对票是正确的。这不是真的,至少不是在所有情况下。
模态对话框通常会自己处理 AWT 事件。如果你运行代码
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
JOptionPane.showInputDialog("hello");
}
});
然后break,查看线程,你会看到只有一个EventQueue线程。JOptionPane 的 show() 方法本身会泵送事件。
Spin和 Foxtrot等框架采用相同的方法——它们允许您在 EDT 上创建一个长时间运行的阻塞方法,但通过泵送事件本身来保持事件的流动。swing 可以有多个调度线程(我确信旧版本的 swing 就是这种情况),但现在多核很常见,并发问题,特别是确保一个线程上的更改正确发布到其他线程,意味着使用多个 EDT 会在当前实现中产生错误。查看 多个 Swing 事件调度线程
这是 AWT 的线程,而不是 Swing 的线程。
无论如何,AWT 在show
. 阻塞窗口的输入事件被阻塞。重绘事件、未阻塞窗口的事件和一般事件照常调度。
您可以通过添加以下行来查看:
Thread.dumpStack();
进入模式对话框的均匀处理,或者更容易地从命令行使用jstack
或在应用程序的命令窗口中使用ctrl-\
/ ctrl-break
。
Foxtrot库滥用这一点来提供更程序化的(而不是事件驱动的)模型。当从应用程序 EDT 调用时,WebStart/Java 插件也使用它来为 JNLP 服务和其他服务提供对话框。