默认情况下,所有Swing组件都在EDT上运行吗?

时间:2014-08-09 07:18:28

标签: java multithreading swing

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

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

由于

3 个答案:

答案 0 :(得分:6)

记住,对象不会存在于线程上,只会在线程上执行方法。

来自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组件。
  4. 这个question包含一些可以帮助您自动检测错误的工具(尽管不是全部)。

答案 1 :(得分:4)

  

默认情况下我的Swing应用程序在EDT上运行,或者他们是在不同的线程上运行的,我很幸运,没有任何问题吗?

他们大多是在EDT上跑。 Swing所做的所有绘画和更新都在EDT上。你在代码库中专门做的事情,你知道在EDT上没有,是EDT上没有的代码。所以这些操作就像查询JLabel的文本,设置JLabel的文本或初始化JLabel本身一样。

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

  

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

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

  

我是否必须通过调用SWUNUtilities.invokeLater()

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

是,或者invokeNow()

答案 2 :(得分:1)

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

所有Swing组件(或者根本不重要)MIST可以在事件调度线程的上下文中被访问,一旦它们被添加到可显示的容器(连接到本地对等体)。

这使得Swing组件不是线程安全的,你有责任确保从EDT正确地修改/访问它们,框架不会为你做这个

请查看Concurrency in Swing了解详情

相关问题