SwingUtilities.invokeAndWait()详解

SwingUtilities.invokeAndWait() 是Swing 框架提供的一个方法,用于将一个 Runnable 对象放入事件派发线程(Event Dispatch Thread,EDT)并等待其执行完毕。它的主要作用是在非EDT 线程中安全地更新Swing 组件,确保对UI 的访问是线程安全的。与 SwingUtilities.invokeLater() 类似,但 invokeAndWait() 会阻塞调用线程,直到EDT 完成了任务的执行。

主要功能和作用:

  • 线程安全地更新UI:

    Swing 组件是线程不安全的,只能在EDT 中进行访问和修改。invokeAndWait() 确保了在非EDT 线程中更新UI 的操作被安全地放入EDT 中执行。

  • 同步执行:

    invokeAndWait() 类似于一个同步调用,它会阻塞当前线程,直到EDT 执行完指定的任务并返回。

  • 替代 invokeLater() 的场景:

    当需要立即获取任务执行结果,并且当前线程需要等待时,可以使用 invokeAndWait() 替代 invokeLater()

使用场景:

  1. 需要立即获取UI 状态:

    当一个线程需要获取某个UI 组件的当前状态(例如,文本框中的文本内容)时,可以使用 invokeAndWait() 确保在获取状态之前,EDT 已经完成了对该组件的更新。

  2. 防止死锁:

    在某些情况下,使用 invokeAndWait() 可以避免死锁。例如,当一个线程需要等待另一个线程持有的锁,并且该锁的释放操作需要在EDT 中完成时,可以使用 invokeAndWait() 将释放锁的操作放入EDT 中执行。

代码示例:

Java 复制代码
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;

public class InvokeAndWaitExample {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("InvokeAndWait Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 200);
            frame.setVisible(true);

            // 在非 EDT 线程中更新 UI
            new Thread(() -> {
                try {
                    SwingUtilities.invokeAndWait(() -> {
                        // 在 EDT 中执行的代码
                        frame.setTitle("Updated Title");
                        System.out.println("Title updated in EDT");
                    });
                    // EDT 执行完毕后,继续执行后续代码
                    System.out.println("Title update complete");
                } catch (InterruptedException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }).start();
        });
    }
}

注意事项:

  • 避免在EDT 中调用 invokeAndWait():

    如果在EDT 中调用 invokeAndWait(),会导致死锁,因为EDT 会等待自己执行完毕。可以通过SwingUtilities.isEventDispatchThread()方法来判断当前线程是否为事件分派线程(EDT),若返回true,表示当前线程是EDT线程

  • 尽量使用 invokeLater():

    除非必须,否则应尽量使用 invokeLater(),因为它不会阻塞调用线程,避免潜在的性能问题。

  • 处理异常:

    invokeAndWait() 方法可能会抛出 InterruptedExceptionInvocationTargetException 两种异常,需要进行适当的异常处理。

总结:

SwingUtilities.invokeAndWait() 是一个强大的工具,用于在非EDT 线程中安全地更新Swing 组件。理解其工作原理和注意事项,可以帮助开发者编写更加稳定和高效的Swing 应用程序。

相关推荐
元界metalite2 分钟前
SpringBoot整合Druid-连接池参数为什么不能照抄
后端
fatcoder7 分钟前
玩转Nginx 09 — 运维排障:三场"火灾"实战演练
前端·后端·nginx
元界metalite11 分钟前
MyBatis通用查询如何避免SELECT *?MetaLite如何按需返回字段
后端
Flynt35 分钟前
Go 1.27 升了一波,泛型方法和 JSON v2 真香但有个坑
后端·go
我会冲击波1 小时前
vibe coding 一个多月,我把 Claude Code + Pi 做成了桌面 IDE,还给它移植了 VS Code 的编辑体验
前端·javascript·后端
我是谁的程序员1 小时前
Windows / Linux / Mac 上不用 Xcode 把 IPA 上传到 App Store,upload 命令详解
后端·ios
凌涘1 小时前
JWT 登录鉴权 Demo 拆解
后端
JimmtButler1 小时前
从 Java 到 JS:我终于把闭包想明白了
javascript·后端
掘金者阿豪2 小时前
Codex 怎么突然变慢了?一个需求跑几十分钟,我才发现它的工作方式已经变了
前端·后端
Zadig2 小时前
Zadig 全面支持 CRD,至此所有 K8s 资源类型均可一键发布!
后端·devops