在这里作为答案提供的许多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 article,从主线程构建UI是安全的:
一些方法是线程安全的:在Swing API文档中, 线程安全的方法用这个文字标记:
此方法是线程安全的,但大多数Swing方法都不是。
应用程序的GUI通常可以在主体中构建和显示 thread:以下典型代码是安全的,只要没有组件 (摆动或其他方式)已经实现:
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,或者这只是一种习惯,要记住在其他情况下这样做吗?
答案 0 :(得分:16)
“ Swing单线程规则:应该从事件派发线程中创建,修改和查询 的Swing组件和模型。” - {{3 },还讨论了Java Concurrency in Practice和here。如果不遵循此规则,则您无法可靠地构造,修改或查询可能假定您 遵循该规则的任何组件或模型。程序可以出现以正常工作,只会在不同的环境中神秘地失败。由于违规行为可能不明确,请使用here提及的方法之一验证用法是否正确。
答案 1 :(得分:1)
在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上的代码 - 如果您想要更加安心,使用它不会有任何损失。
答案 2 :(得分:1)
我认为使用SwingUtiltities.invokeLater()
只是一种更简单的异步执行代码的方法。有时某些应用程序需要它:例如,您可以同时创建2个单独的窗口。而已。