5

这个简单的问题让我感到困惑。setVisible您可以通过设置框架的属性来显示 JAVA GUI 应用程序true。但是在我在互联网上找到的几乎所有示例中,它们都使用单独的线程来做同样的事情。

他们做这样的事情,

SwingUtilities.invokeLater(new Runnable() {

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

我发现这两种方法没有区别。但是肯定有什么特殊的原因,这就是为什么大家都这样。

有人能解释一下吗..谢谢!

4

6 回答 6

9

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

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

我建议您熟悉一些资源:

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

更新

这是我一直在寻找的博客:P

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

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

于 2012-10-01T03:11:57.427 回答
3

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

这是因为重绘是在单个线程上执行的,通过使用invokeLater您可以让该线程管理它,而不会因 Swing 缺乏线程安全性而产生潜在的问题。使用该语法,您可以将该指令委托给在适当的线程上执行,该线程是管理 GUI 元素的线程。

于 2012-10-01T03:13:10.447 回答
3

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

于 2012-10-01T03:13:47.887 回答
3

Swing 类不是线程安全的;它们仅从对它们的所有操作都在同一线程(事件调度线程或 EDT)上执行这一事实获得线程正确性。因此,任何时候您与 Swing 对象交互时,它都必须在 EDT 上——SwingUtilities.invokeLater这是一个很好的方法。

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

于 2012-10-01T03:14:28.800 回答
3

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

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

于 2012-10-01T03:16:30.350 回答
1

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

于 2012-10-02T01:38:15.010 回答