Java 事件分派线程说明

2022-08-31 15:13:22

我最近开始学习和探索Java中GUI编程的基础知识。

我已经编程了一段时间,我只做过后端工作或工作,因此我最接近用户界面的是命令控制台(我知道这很尴尬)。

我正在使用Swing,据我所知,这意味着通过扩展,我也在使用AWT。

我的问题基于这段代码:

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        new frame.setVisible(true);
    }
} );

我已经研究了一段时间,因为我想完全理解这段奇怪的代码,并且多次遇到“事件调度线程”一词。如果我错了,请纠正我,但正如我所理解的那样;它与使用多个线程以及Java Swing如何解释这些线程有关。我还收集了上面的代码用于确保在创建窗口之前所有线程都是“安全的”,因此调用Later?

我读过:

“您只能从事件调度线程调用对帧进行操作的方法”

并且只有在某些情况下,您才能从 main 方法调用对帧进行操作的方法。

有人可以向我澄清事件调度线程到底是什么吗?

它与多个执行线程有何关系,以及从 main 方法调用这些线程如何不安全?另外,为什么我们需要这个调用Later?

我们能不能像创建任何其他对象一样创建窗口?

我在研究中遇到了一些障碍,因为我没有掌握这些关系和想法。

旁注是,我喜欢将我的知识建立在深入理解的基础上,因为我相信这可以带来最好的整体结果,从而带来最好的计划。如果我深入了解某些东西是如何工作的,那么你可以有效地使用这些技巧和调整,而不仅仅是将它们重新输入代码,所以请不要害怕给我一些额外的深入解释并拓宽我的知识。

谢谢。


答案 1

事件调度线程是由 AWT 管理的特殊线程。基本上,它是一个在无限循环中运行的线程,处理事件。

java.awt.EventQueue.invokeLaterjavax.swing.SwingUtilities.invokeLater 方法是一种提供将在事件队列上运行的代码的方法。编写在多线程环境中安全的 UI 框架非常困难,因此 AWT 作者决定只允许在单个特殊线程上对 GUI 对象执行操作。所有事件处理程序都将在此线程上执行,所有修改 GUI 的代码也应在此线程上运行。

现在,AWT通常不会检查您是否没有从另一个线程发出GUI命令(C#的WPF框架确实这样做),这意味着可以编写大量代码并且对此几乎不可知,并且不会遇到任何问题。但这可能会导致未定义的行为,因此最好的办法是始终确保 GUI 代码在事件调度线程上运行。 提供了执行此操作的机制。invokeLater

一个典型的例子是,您需要运行长时间运行的操作,例如下载文件。因此,您启动一个线程来执行此操作,然后在完成后,用于更新 UI。如果您没有使用,而只是直接更新了 UI,则可能存在争用条件,并且可能会发生未定义的行为。invokeLaterinvokeLater

维基百科有更多信息

另外,如果您好奇为什么AWT作者不只是使工具包多线程,这里有一篇好文章。


答案 2

EventDispatchThread(EDT)是专门为Swing GUI和*Swing的相关事件保留的特殊线程,例如创建/更改/更新Swing JComponents,更多用于此处此处的提问

从 到 GUI 的所有输出都必须包装到 invokeLater() 中,从同步对象到BackGround TasksRunnable#ThreadinvokeAndWait();


推荐