【问题标题】:Use of multiple threads in a Java program and vs need to create Swing objects on EDT在 Java 程序中使用多个线程以及需要在 EDT 上创建 Swing 对象
【发布时间】:2011-02-01 03:51:48
【问题描述】:

Re: 在 Event-Dispatch 线程上创建 Swing 对象的要求。

我正在开发一个应用程序,其目的是监视和显示各种远程嵌入式服务器的状况。我对 Java 很陌生,我对 Swing 对象和 EDT 的要求的理解还不完整。

主 GUI 在 EDT 上以通常的方式启动,如下所示,

    javax.swing.SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            createAndShowGUI();
        }
    });

然后用户可以选择对应于一台或另一台远程机器的一个或多个菜单选项。这样的效果就是每次新建一个线程如下

                new Thread(new VoterStatus(itemNumber)).start();

它调用 VoterStatus 的类“run”方法,该方法又创建一个带有 JFrame 的新窗口。新线程是 VoterStatus 类的一个实例,然后询问(TCP 等)指定的特定远程(itemNumber),收集各种信息位并在 JFrame 中显示它们。

可能存在与 VoterStatus 实例相对应的任意数量的此类线程,它们都会更新它们自己的窗口。这些不同的窗口/JFrame/任务之间没有数据共享。

这似乎工作得很好,但是安全吗?

我是否违反了在 EDT 上创建 Swing 组件的规则?

使用 SwingWorker 类会有好处吗?

如果 Java 程序员在此类问题上更有经验,我将不胜感激。

谢谢 史蒂夫

【问题讨论】:

  • 您是否只使用 EDT 来启动主 GUI?如果是,那么一切都很好。但是,如果后续窗口也在 EDT 中创建,并且它们的创建时间足够长(即 > 200 毫秒),您的 GUI 将在新窗口创建期间冻结。
  • 嗨 Rogach - cmets 似乎与其他几个答案略有不同,但如果确实如此,我更喜欢它。我在 EDT 上创建主 GUI,但其他窗口是在 EDT 中启动的线程上启动的。还有什么想法。谢谢史蒂夫

标签: java multithreading events swing dispatch


【解决方案1】:

来自 Swing 教程中标题为 The Event Dispatch Thread 的部分

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

我总是在 EDT 上调用我的方法,所以我不会浪费时间追逐小精灵。

编辑:

我刚刚阅读了另一篇文章,其中指出注释“线程安全”已从 JDK7 API 的许多方法中删除。 http://forums.oracle.com/forums/thread.jspa?threadID=2167051。这似乎是确保影响 GUI 的所有方法都在 EDT 上执行的另一个原因。

【讨论】:

  • +1 就像轨道轰炸一样,这是唯一确定的方法。 :-)
  • repaint() 是在 EDT 外运行始终安全的方法的一个很好的例子。
【解决方案2】:

@camickr 拥有它的权利。不正确同步的程序可能似乎大部分时间都可以工作,但结果并不可靠。讨论了几种相关的方法hereSwingWorkerFuture 接口的一个特别方便的实现,因为process() 在事件调度线程上运行。

【讨论】:

    【解决方案3】:

    您可能是安全的,但您可以通过在 EDT 中创建其他 UI 组件来确保安全,就像您在主应用程序中所做的那样。

    但是,我建议采用不同的方法。与其启动一个新的Thread 来为每个新的VoterStatus 创建窗口和内容,不如在EDT 中创建UI 组件以响应来自菜单或其他内容的ActionEvents,并仅在不同的线程。然后获取结果并使用 EDT 显示它们。正如您所建议的,SwingWorker 非常适合此用途 - 这正是它的设计用途。这对我来说代表了更清晰的分离,尽可能地将 UI 内容与网络内容分开。

    【讨论】:

      【解决方案4】:

      我并没有真正回答我自己的问题,但我确实要感谢那些回答并提出一两个后续问题的人。

      Rogash 评论说,如果我只是在 EDT 上创建 GUI,我会没问题,但这似乎不太符合对规则的严格解释?

      附加线程是在 EDT 中创建的,但它们仍然是单独的线程。

      虽然可能需要更好地分离 GUI 和通信,但我预计这会给主要 GUI 代码增加相当大的复杂性,因为它必须确定哪个窗口引发各种事件,然后更新正确的窗口,更不用说各种线程和主 GUI 线程之间的通信。也许我夸大了这个困难(我还没有设计或考虑过如何编码),但它似乎更复杂。每个线程/JFrame 已经有几个导致潜在事件的 JToggleButton 数组(30 个元素)和 10 个左右的 JTextField 数组,它们具有相同数量的需要更新的元素。

      当然,如果我的方法不安全,我就必须改变它,就是这样!

      实际上,我想知道是否最好让事情保持原样,并使用互斥锁或信号量来确保一次只有一个线程访问 Swing 方法。确实没有长时间的用户操作或任何其他活动需要很长时间,只是收到了大量需要更新屏幕显示的 TCP 或 UDP 数据包。

      再次感谢 史蒂夫

      PS 我尝试在此论坛上注册,但我认为此讨论将保留在我未注册的角色中。

      【讨论】:

        猜你喜欢
        • 2014-03-31
        • 2012-08-21
        • 1970-01-01
        • 2013-01-20
        • 1970-01-01
        • 2014-12-10
        • 2018-02-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多