3

我最近发现了一个示例代码:

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

createAndShowGUI()方法打开用户界面窗口。然后我尝试将代码修剪如下:

public static void main(String[] args) {
    createAndShowGUI();
}

两个版本都同样好用。有什么不同?

4

4 回答 4

10

99% 的时间任一代码都可以工作。

然而,Swing 的设计使得对 Swing 组件的所有更新都应该在事件调度线程 (EDT) 上完成。阅读有关并发的 Swing 教程以获取更多信息。

问题是 1% 的时间它可能不起作用。您不想浪费时间尝试调试随机问题。

于 2013-10-03T19:04:35.233 回答
4

SwingUtilities.invokeLater确保代码在事件调度线程 (EDT) 上执行。Swing 是单线程的,所有组件的实例化和显示都应该在 EDT 上进行。事情可能看起来不正常,但你可能会遇到问题。

于 2013-10-03T19:05:22.680 回答
3

Swing 具有基于单线程事件循环的设计,并且不是线程安全的,只有线程安全部分是一组invokeXXX()用于将控制权转移到 Swing 事件循环的方法。

您的“损坏”代码工作得很好,因为没有其他东西试图同时从事件循环中触及 Swing 数据结构的同一部分。

于 2013-10-03T19:07:13.627 回答
3

由 启动的“主”线程JVM不是事件调度线程。

来自事件调度线程

一些 Swing 组件方法在 API 规范中被标记为“线程安全”;这些可以从任何线程安全地调用。所有其他 Swing 组件方法都必须从事件分派线程中调用。忽略此规则的程序可能在大多数情况下都能正常运行,但会出现难以重现的不可预测的错误。

于 2013-10-03T19:10:36.183 回答