我最近开始学习和探索Java中GUI编程的基础知识。
编程已经有一段时间我只完成了后端工作或工作,因此最接近用户界面的是命令控制台(我知道这很尴尬)。
我正在使用Swing,据我所知,这意味着我也使用AWT。
我的问题是基于这段代码:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new frame.setVisible(true);
}
} );
我一直在研究这个问题,因为我想完全理解这段奇怪的代码,并多次遇到“事件调度线程”这个术语。如果我错了,但正如我所理解的那样纠正我;它与使用多个线程以及Java Swing如何解释这些线程有关。我也收集到上面的代码用于确保所有线程在创建窗口之前是“安全的”,因此invokeLater?
我读过:
“您只能从Event-Dispatching Thread中调用对该帧进行操作的方法”
并且只有在某些情况下才能调用main方法对框架进行操作的方法。
有人可以向我澄清一下Event-Dispatching Thread究竟是什么?
它与多个执行线程的关系如何以及如何从main方法调用这些线程是不安全的?另外我们为什么需要这个invokeLater?
我们不能像其他任何对象一样创建窗口吗?
我在研究中遇到了一些障碍,因为我没有抓住这些关系和想法。
旁注是我喜欢将我的知识建立在深入理解的基础上,因为我相信这会带来最好的整体结果,因此也是最好的计划。如果我深入了解某些内容是如何工作的,那么您可以有效地使用提示和调整,而不仅仅是将它们重新编入代码中,所以请不要害怕给我一些额外的深入解释并扩展我的知识。< / p>
谢谢。
答案 0 :(得分:56)
event dispatch thread是由AWT管理的特殊线程。基本上,它是一个在无限循环中运行的线程,处理事件。
java.awt.EventQueue.invokeLater
和javax.swing.SwingUtilities.invokeLater
方法是一种提供将在事件队列上运行的代码的方法。编写在多线程环境中安全的UI框架非常困难,因此AWT作者决定只允许对GUI对象的操作在单个特殊线程上进行。所有事件处理程序都将在此线程上执行,所有修改GUI的代码也应该在此线程上运行。
现在AWT通常不会检查你是不是从另一个线程发出GUI命令(C#的WPF框架确实这样做了),这意味着它可以编写大量代码并且对此非常不可知并且不会遇到任何问题。但这可能会导致未定义的行为,因此最好的办法是始终确保GUI代码在事件派发线程上运行。 invokeLater
提供了执行此操作的机制。
一个典型的例子是您需要运行长时间运行的操作,例如下载文件。因此,您启动一个线程来执行此操作,然后在完成后,使用invokeLater
更新UI。如果您没有使用invokeLater
,而只是直接更新了UI,则可能会出现竞争条件,并且可能会发生未定义的行为。
Wikipedia has more information
此外,如果您很好奇为什么AWT作者不仅仅使工具包成为多线程,here是一篇好文章。
答案 1 :(得分:12)
EventDispatchThread
(EDT)是仅为Swing GUI和* Swing的相关事件保留的特殊线程,例如创建/更改/更新Swing JComponents,更多针对提问题here和here
从BackGround Tasks
Runnable#Thread
向GUI输出的所有内容必须包含在invokeLater()中,从同步对象转换为invokeAndWait();