【问题标题】:Do all Swing components run on the EDT by default?默认情况下,所有 Swing 组件都在 EDT 上运行吗?
【发布时间】:2014-10-02 16:25:15
【问题描述】:

我是 Java 新手,在阅读了许多关于线程和 Swing 的文章后,我了解到 Swing 方法的所有调用都应该在 EDT 上完成,因为 Swing 不是线程安全的。然而,在阅读 EDT 之前,我已经编写了几个相当长的 Swing 应用程序。我所有的应用程序都运行得很好。所以我的问题是我的 Swing 应用程序是默认运行在 EDT 上还是运行在不同的线程上,我很幸运没有遇到任何问题? 例如,如果我将 JButton 添加到 JPanel 或 JFrame,或者如果我只是调用 JTextField 的 Field.setText(),这些操作是否会默认在 EDT 上运行? 如果答案是否定的,那么我是否必须通过调用 SwingUtilities.invokeLater()

显式发送我的所有 Swing 组件的方法实现以在 EDT 上运行

谢谢

【问题讨论】:

标签: java multithreading swing


【解决方案1】:

记住对象并不存在于线程上,只有方法的执行发生在线程上。

所有从 Swing 组件(通过侦听器)出现的动作都会自动在 EDT 上运行。

例如,您单击一个按钮,onClicked() 函数将在 EDT 上运行,因此您无需执行任何操作。

如果您不明确创建任何线程,您的基本应用程序将有一个主线程和一个 EDT(以及许多其他线程,在您开始使用额外的框架之前,您不会意外地在这些线程上执行您的代码)。

您必须手动在 EDT 上构建 GUI。如您所见here,这可以在您的主线程中完成,如下所示:

   SwingUtilities.invokeLater(new Runnable() { 
        public void run() {            
            MyWindow window = new MyWindow ();
            window.setVisible(true);
        }
    });

如果您未能正确使用 EDT。一切似乎都可以正常工作,但时不时会出现非常奇怪的行为(因为两个线程会做某事而不是一个)。

所以总而言之,你必须使用invokeLater(),或者在某些例外情况下使用invokeNow()

  1. 从主线程构造 Swing 组件。
  2. 从您个人创建的线程中调用 swing 组件。
  3. 从框架创建的线程上的事件中调用 swing 组件。

这个question 包含一些可以帮助您自动检测错误的工具(尽管不是全部)。

【讨论】:

    【解决方案2】:

    我的 Swing 应用程序默认在 EDT 上运行还是在不同的线程上运行,我很幸运没有遇到任何问题?

    它们主要在 EDT 上运行。 Swing 自己进行的所有绘制和更新都在 EDT 上。你在你的代码库中专门做的任何你知道不在 EDT 上的事情,就是不在 EDT 上的代码。因此,这些操作包括查询 JLabel 的文本、设置 JLabel 的文本或初始化 JLabel 本身。

    您在代码库中实现的由 Swing 执行的各种侦听器方法在 EDT 上执行(只要 Swing 调用它,而不是您自己)。因此,在这些方法中,您可以查询/修改 Swing 组件,但请记住正确地传入和传出您提供给 Swing 组件或以线程安全方式从 Swing 组件查询的任何数据。

    例如,如果我创建一个 JButton 并将其添加到 JPanel 或 JFrame,这些操作是默认在 EDT 上运行还是不运行?

    对象的初始化发生在您创建它们的任何线程上,Swing 对象的其余修改也是如此(例如将一个组件添加到另一个组件)。我不知道有哪些 Swing 组件的公共方法实现包含在它们自己的 invokeNow() 或 invokeLater() 调用中,因此最好假设所有操作部分都发生在您调用原始方法的任何线程上。

    我是否必须通过调用SwingUtilities.invokeLater() 显式发送我的所有Swing 组件和方法以在EDT 上运行

    是,或者 invokeNow()

    【讨论】:

    • 非常感谢,您的帮助很大。从现在开始,我会更加小心,并尝试将我所有的 Swing 方法实现发送到 EDT 上运行
    • @user3769877 没问题。仔细检查您的代码是否在 EDT 上的一个好方法是打印 isEventDispatchThread() 的结果。当您怀疑某个事件是否在 EDT 上时很有帮助。
    【解决方案3】:

    组件将在它们被调用的线程上下文中被访问,这会导致问题......

    一旦将所有 Swing 组件(或足够无关紧要)添加到可显示容器(附加到本机对等体),MIST 就可以在事件调度线程的上下文中访问。

    这使得 Swing 组件不是线程安全的,您有责任确保从 EDT 正确修改/访问它们,框架不会为您执行此操作

    查看Concurrency in Swing了解更多详情

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多