2

所以我看过无数不同的GUI教程,都说要使用这段代码:

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

}

尽管我可能不太明白这到底是做什么的,但由于我对 GUI 有点陌生,但我确实了解它的基本功能......或者我是这么认为的。但后来我,作为一个实验,把它全部删掉,然后就离开了:

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

它似乎奏效了。所以现在我有一个问题:保留我的第一段代码而不是仅仅使用第二段代码的目的是什么,而第二段代码看起来也一样好用?如果有必要,如果我不使用它会怎样?

4

1 回答 1

4

简而言之,是的,每当您对任何 Swing 对象进行更改时,都必须这样做(除非 API 说它们是线程安全的)。

您对 GUI 所做的任何更改都必须在事件调度线程 (EDT) 上进行,因为 Swing 对象不是线程安全的。来自事件调度线程教程

Swing 事件处理代码在称为事件分派线程的特殊线程上运行。大多数调用 Swing 方法的代码也在这个线程上运行。这是必要的,因为大多数 Swing 对象方法都不是“线程安全的”:从多个线程调用它们可能会导致线程干扰或内存一致性错误。一些 Swing 组件方法在 API 规范中被标记为“线程安全”;这些可以从任何线程安全地调用。所有其他 Swing 组件方法都必须从事件分派线程中调用。忽略此规则的程序可能在大多数情况下都能正常运行,但会出现难以重现的不可预测的错误。

调用 SwingUtilities.invokeLater 可确保在 EDT 上调用可运行的代码,并且不会出现奇怪的错误。这就是为什么当您删除该代码时,它看起来一切正常,因为在您测试的情况下它可能确实如此。但它可能并非总是如此,而且您不希望代码有时有效或存在时间问题。

于 2014-10-02T21:44:30.547 回答