Java中的主线程与UI线程

在这里作为答案给出的许多Swing片段中,从main方法调用SwingUtilities#invokeLater

 public class MyOneClassUiApp { private constructUi() { // Some Ui related Code } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new MyOneClassUiApp().constructUi(); } }); } } 

但根据Threads and Swing的文章 ,从主线程构造UI是安全的:

一些方法是线程安全的:在Swing API文档中,线程安全的方法用这个文本标记:

虽然大多数Swing方法都不是,但这种方法是线程安全的。

应用程序的GUI通常可以构造并显示在主线程中:只要没有实现组件(Swing或其他),以下典型代码是安全的:

 public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame("Labels"); // Add components to // the frame here... f.pack(); f.show(); // Don't do any more GUI work here... } } 

那么,是否有一个真正的(线程安全)理由通过SwingUtilities#invokeLater在main中构建UI,或者这只是一种习惯,要记住在其他情况下这样做吗?

Swing单线程规则 :应该从事件派发线程创建,修改和查询Swing组件和模型。” – Java Concurrency in Practice ,也在这里和这里讨论过。 如果您遵循此规则,则无法可靠地构造,修改或查询可能假定您遵循该规则的任何组件或模型。 程序似乎可以正常工作,只是在不同的环境中神秘地失败。

在main方法中创建Swing UI是安全的,因为在设置UI之前如何显示其他组件? 只要你没有在屏幕上抛出一些东西你就没事了。 换句话说,这会很糟糕:

 public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame("Labels"); // Add components to // the frame here... f.pack(); f.show(); // now make another frame: JFrame f2 = new JFrame("Labels2"); // Add components to the 2nd frame here... f2.pack(); f2.show(); } } 

如果您执行了上述操作,那么您将启动并运行JFrame f ,然后您将从事件调度线程(EDT)中添加Swing UI组件。 invokeLater在EDT上运行代码 – 如果你想要额外的安心,使用它也不会有害。

我认为使用SwingUtiltities.invokeLater()只是一种异步执行某些代码的简单方法。 有时某些应用程序需要它:例如,您可以同时创建2个单独的窗口。 而已。