【问题标题】:Why is it important to use invokeLater?为什么使用 invokeLater 很重要?
【发布时间】:2013-10-10 14:54:53
【问题描述】:

我最近找到了一个示例代码:

public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

createAndShowGUI() 方法打开一个用户界面窗口。然后我尝试将代码修剪如下:

public static void main(String[] args) {
    createAndShowGUI();
}

两个版本的效果一样好。有什么区别?

【问题讨论】:

  • 在大多数情况下,它同样可以正常工作,但偶尔您的 GUI 线程和更新 GUI 的线程会导致奇怪且无法重现的行为。这就是测试多线程代码的问题,你可以运行它几天并更改一些小的东西,突然它经常出现。

标签: java swing event-dispatch-thread invokelater


【解决方案1】:

99% 的时间任一代码都可以工作。

然而,Swing 的设计使得对 Swing 组件的所有更新都应在事件调度线程 (EDT) 上完成。阅读Concurrency 上的 Swing 教程了解更多信息。

问题在于 1% 的时间它可能不起作用。您不想浪费时间尝试调试随机问题。

【讨论】:

    【解决方案2】:

    SwingUtilities.invokeLater 确保代码在事件调度线程 (EDT) 上执行。 Swing 是单线程的,所有组件的实例化和显示都应该在 EDT 上进行。事情似乎可以正常工作,但您可能会遇到问题。

    【讨论】:

      【解决方案3】:

      Swing 具有基于单线程事件循环的设计,并且不是线程安全的,只有线程安全部分是一组用于将控制权转移到 Swing 事件循环的 invokeXXX() 方法。

      您的“损坏”代码工作得很好,因为没有其他东西试图同时从事件循环中触及 Swing 数据结构的同一部分。

      【讨论】:

        【解决方案4】:

        JVM 启动的“主”线程不是事件调度线程。

        来自The Event Dispatch Thread

        一些 Swing 组件方法在 API 规范中被标记为“线程安全”;这些可以从任何线程安全地调用。 所有其他 Swing 组件方法都必须从事件分派线程中调用。忽略此规则的程序可能大部分时间都能正常运行,但会出现难以重现的不可预测的错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-19
          • 2011-12-01
          • 2010-12-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-02
          • 2015-09-07
          相关资源
          最近更新 更多