Swing并发和Event-Dispatch Thread

时间:2015-02-02 15:09:24

标签: java multithreading swing event-dispatch-thread

我想知道正确使用java swing的最可接受的方法是什么。我知道在java swing应用程序中默认有两个线程Main Thread和Event-Dispatch。我以这种方式创建和显示窗口。

public class Main {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new MyWindow().initializeAndShow());
    }

但我想知道如何在运行时使用java swing。我的意思是,例如在按钮点击时在JText中设置文本。我需要一直这样做吗?

  SwingUtilities.invokeLater(()-> button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e)
            {

               SwingUtilities.invokeLater(()-jtext.setText("HelloFromAWTThread");
            }
        });      

是否正确,我认为只要按钮也是UI的一部分,所以应该在调度线程中设置监听器或者这不正确? 设置JText也应该在AWT线程中?

1 个答案:

答案 0 :(得分:4)

你想的更简单。

当然,UI元素的修改(e.h.设置标签文本,向按钮添加监听器等)只能由事件派发线程(EDT)完成。

但大部分时间这都不是真正的限制,因为所有事件(例如鼠标点击按钮或按键)都由EDT处理,所以你的听众也会在EDT上执行。

因此,如果您想注册一个监听器,只需执行

button.addActionListener(new ActionListener() {
    /* called by the EDT when the button has been clicked */
    public void actionPerformed(ActionEvent e) {
        jtext.setText("HelloFromAWTThread");
    }
});

甚至更简单的Java 8 lambdas:

button.addActionListener(e -> jtext.setText("HelloFromAWTThread"));

如果你想要运行一个长期运行的任务,它只会变得更复杂,例如耗时的计算(计算100万位PI,进行素数分解等),任何I / O操作(加载文件,执行网络请求)或任何阻塞操作,因为这将占用EDT太长时间并防止它处理UI事件。因此,这些任务应该在不同的线程上运行。但由于不允许从EDT之外的其他线程更新UI,因此您可以移交'通过调用SwingUtilities.invokeLater(updateTask)向EDT发送UI更新任务。