Java Swing中GUI代码的线程同步

本文介绍了在Java Swing中如何进行GUI代码的线程同步,强调了Event-Dispatching Thread的重要性。SwingUtilities的invokeLater()和invokeAndWait()方法用于确保在正确的线程中执行GUI代码,避免死锁。SwingWorker和Timer类可以解决长时间运行任务对响应速度的影响,SwingWorker在后台线程执行耗时任务,并在完成后更新UI。同时,文章提供了使用Timer进行定时更新组件的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GUI代码的线程同步

Swing组件的事件处理和绘画代码,都是被一个线程依次调用的,
这样保证事件处理的同步执行。
这个线程就是 Event-Dispatching Thread。

为了避免可能的死锁,确保Swing组件和model的创建、修改和查找
只在Event-dispatching Thread中调用。

SwingUtilities的invokeLater(Runnable),invokeAndWait(Runnable)
都是将GUI代码加入Event-dispatching Thread的方法。

invokeLater()立即返回,而invokeAndWait()阻塞,直到Event-dispatching Thread
执行完指定的GUI代码。
invokeAndWait()方法也有导致deadlock的可能,尽量使用invokeLater()。

About Realized
Realized means that the component has been painted on screen, or is ready to be painted.
setVisible(true) and pack() cause a window to be realized, which in turn causes the components it contains to be realized.

同步会导致等待,当一个事件处理时间太长,后面的事件处理就得不到响应,给人响应不灵敏的感觉。
SwingWorker或者Timer类可以解决缓解这个问题,
其中SwingWorker是java-tutorials定义的类,不是Swing API。

SwingWorker 让你在利用其它线程执行完耗时任务后,向Event-dispatching Thread中添加GUI代码。
耗时任务写在construct()中,耗时任务后的GUI代码写道finish()中。
public void actionPerformed(ActionEvent e) {
    ...
    if (icon == null) {     //haven't viewed this photo before
        loadImage(imagedir + pic.filename, current);
    } else {
        updatePhotograph(current, pic);
    }
}
...
//Load an image in a separate thread.
private void loadImage(final String imagePath, final int index) {
    final SwingWorker worker = new SwingWorker() {
        ImageIcon icon = null;

        public Object construct() {
            icon = new ImageIcon(getURL(imagePath));
            return icon; //return value not used by this program
        }

        //Runs on the event-dispatching thread.
        public void finished() {
            Photo pic = (Photo)pictures.elementAt(index);
            pic.setIcon(icon);
            if (index == current)
                updatePhotograph(index, pic);
        }
    };
    worker.start();
}

 

可以使用如下的技术,使得Swing程序顺利工作:
●  如果你需要更新组件,但是代码不在Event Listener中,使用invokeLater()或invokeAndWait()向Event-dispacthing Thread添加代码。
●  如果你不能确定你的代码是不是在Event Listener中,你必须弄清楚,程序中方法会被线程调用的情况。很难确定方法被线程的调用情况,可是调用SwingUtilies.isEventDispatchThread()来确定调用方法的线程是不是Event-dispatching Thread。安全起见,你可以把Event Listener外的GUI代码都通过invokeLater()传入EdThread,即使是在EdThread中调用invokeLater()。但是在EdThread中调用invokeAndWait()是会抛出异常的。
●  如果你需要在一段时间的等待后,才更新组件,创建一个Timer,让它来完成这个任务。
●  如果你需要每个一段时间(regular interval)更新组件,使用Timer吧。
* see Also: How to Use Swing Timers:
http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html

 


参考资料:

* How to Use Threads
java tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features
http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值