为什么我应该使用单独的线程在JAVA中显示GUI

这个简单的问题让我很困惑。 您可以通过将frames的setVisible属性设置为true来显示JAVA GUI应用程序。 但在我在互联网上发现的几乎所有例子中,他们都使用一个单独的线程来做同样的事情。

他们做这样的事情,

 SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Frame().setvisible(true); //just take the idea of this line } }); 

我发现这两种方法没有区别。 但必须有一些特殊的原因,这就是每个人都这样做的原因。

有人可以解释一下……谢谢!

以这种方式启动应用程序的主要原因是Swing组件不是线程安全的,因此您需要保证GUI将从哪个线程开始:名为Event Dispatching ThreadEDT )的Event Dispatching Thread 。 如果不这样做,你就无法确定它将从哪个线程开始,但正如几位评论员所指出的那样,主线程保证不是 EDT。

您应该只在EDT中创建,访问或修改UI组件。 否则将导致意外行为(如果您很幸运)和/或脏重绘。

我建议您熟悉一些资源:

  • 事件派遣线程
  • 在AWT和Swing中绘画

您还可以阅读为什么我的样板Java桌面应用程序JFrame在main方法中使用EventQueue.invokeLater?

UPDATE

这是我一直试图找到的博客 :P

这基本上解释了为什么在开始之前将main与EDT同步很重要,它还描述了有关原因的一些细节。

它还描述了为什么许多开发人员在启动他们的应用程序时犯了这个根本性的错误(基本上,我们被告知我们可以,但我们从未真正被允许……糟糕的我们)

因为您在GUI上执行的每个修改都应该在事件调度线程上完成 。 这就是AWTSWING的工作方式。

这是因为重绘是在一个线程上执行的,通过使用invokeLater你让该线程管理它,而没有由于缺乏Swing的线程安全性而发出的潜力。 使用该语法,您可以委派要在适当的线程上执行的指令,该线程是管理GUI元素的线程。

Swing不是线程安全的,所有组件都需要在EDT中初始化。 这将防止诸如死锁之类的问题。

Swing类不是线程安全的; 他们的线程正确性完全取决于它们上的所有操作都在同一个线程(事件调度线程或EDT)上执行。 所以每当你与Swing对象交互时,它必须在EDT上 – 而SwingUtilities.invokeLater是一个很好的方法。

没有那个调用,如果你只是从任何一个”线程调用setVisible(true) ,你将没有任何线程安全性,并且Frame甚至可能看不到该方法的操作。 更糟糕的是, Frame只能看到一些动作,打破内部假设和不变量,导致奇怪的行为,崩溃或死锁。

几乎任何调用Swing方法的操作都必须在Swing Event Dispatch线程上运行。 invokeLater()是确保此不变量成立的方法。 在这里阅读更多相关信息。

另请注意,大多数其他GUI工具包也是如此,例如.NET,MFC等中的表单。

Java gui框架被设计为一个线程来强制执行线程安全:这种技术称为线程限制。 因此,必须在事件调度线程(EDT)中执行任何gui操作,例如组件创建,模型创建,事件发送等。 您描述的方式是在EDT中排队操作的一种方法。