【问题标题】:Why to use SwingUtilities.invokeLater in main method?为什么在 main 方法中使用 SwingUtilities.invokeLater?
【发布时间】:2013-02-24 11:24:01
【问题描述】:

经过多年的 Java 编程,我总是习惯于创建这样的 main() 方法:

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

但最近我从网上研究了一些代码,有时看到这个而不是上面通常使用的main()

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

我只是想知道:

  • 为什么要使用这个而不是通常的main() 方式?我试一试看不出有什么不同。
  • 这两种方式有什么区别?

感谢您阅读我和您的回答。

【问题讨论】:

    标签: java swing main swingutilities invokelater


    【解决方案1】:

    文档解释了原因。来自Initial Threads

    为什么初始线程不简单地创建 GUI 本身?因为几乎所有创建 Swing 组件或与 Swing 组件交互的代码都必须在事件调度线程上运行。

    来自The Event Dispatch Thread

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

    【讨论】:

    • 我明白了,很有趣。感谢您提供链接并强调了重要内容。
    • 是否有一个清晰的小例子说明如果 main 直接调用 runProgram() 会出现什么问题?据我所知,这里显示的链接参考资料和摘录似乎都没有回答这个问题。
    【解决方案2】:

    因为VM启动的线程“main”不是事件调度线程

    【讨论】:

      【解决方案3】:

      API 中的一些 Swing 组件不是线程安全的,这意味着它们可能会导致死锁等问题,因此最好使用 Swing 提供的 Event Dispatcher 线程而不是主线程来创建和更新此类 Swing 组件或从 main 创建的任何其他线程。

      【讨论】:

        【解决方案4】:

        虽然上面的答案都是正确的,但我认为它们缺乏正确的解释。

        是的,与 Swing 交互的所有事情(创建 UI、更新 UI、添加新组件或布局等)都应始终在 AWT 事件调度线程上完成(有关该主题的更多信息,请参阅 this post) .

        SwingUtilities.invokeLater() 将您的代码放入事件调度线程 (EDT) 的 FIFO 队列中,因此只要它完成了它正在执行的其他任务,它就会从 EDT 执行。


        话虽如此,EDT 应该专门用于运行与 Swing 相关的可快速执行的任务(如果阻止 EDT,就会阻止整个 UI)。

        如果您不使用 Swing/AWT(例如 JavaFX 应用程序或终端应用程序),则在 main 方法上使用 SwingUtilities.invokeLater() 毫无意义。

        如果您想要执行一些与 Swing 完全无关但需要启动 Swing 的任务(例如,在类似 MVC 的应用程序中启动模型和控制器),您可以从 EDT 中执行此操作或主线程(有关此主题的讨论,请参阅 this post)。

        【讨论】:

          猜你喜欢
          • 2015-11-13
          • 2011-04-02
          • 1970-01-01
          • 2015-03-09
          • 2015-09-19
          • 2014-07-01
          • 1970-01-01
          • 2014-01-07
          • 2011-08-29
          相关资源
          最近更新 更多