为什么使用invokeLater很重要?

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

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

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

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

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

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

但是,Swing的设计使得Swing组件的所有更新都应该在Event Dispatch Thread(EDT)上完成。 阅读有关并发的Swing教程以获取更多信息。

问题是1%的时间可能无法正常工作。 您不想浪费时间尝试调试随机问题。

SwingUtilities.invokeLater确保代码在Event Dispatch Thread(EDT)上执行。 Swing是单线程的,所有组件实例化和显示都应该在EDT上进行。 事情似乎不然,但你可能会遇到问题。

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

你的“破解”代码工作正常,因为没有其他东西试图同时从事件循环中触摸Swing数据结构的相同部分。

JVM启动的“main”线程不是Event Dispatch Thread。

来自事件派遣线程

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