为啥在 main 方法中使用 SwingUtilities.invokeLater?
Posted
技术标签:
【中文标题】为啥在 main 方法中使用 SwingUtilities.invokeLater?【英文标题】: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()
方式?我试一试看不出有什么不同。
这两种方式有什么区别?
感谢您阅读我和您的回答。
【问题讨论】:
【参考方案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)。
【讨论】:
以上是关于为啥在 main 方法中使用 SwingUtilities.invokeLater?的主要内容,如果未能解决你的问题,请参考以下文章
无法在 main() 方法中实例化字段(实例变量)。为啥??爪哇