【问题标题】:How can I make multiple Jframes consume data from the same Thread in Java?如何让多个 Jframe 使用 Java 中同一线程的数据?
【发布时间】:2026-02-24 16:00:02
【问题描述】:

我有一个程序,必须输出称重秤的数据。它使用线程从 rs232 源连续读取数据,并且必须以图形方式输出数据。用户可以根据需要打开和关闭任意数量的 Jframe,并且所有 Jframe 都必须显示从 JTextArea 中的 rs232 读取的相同数据。我该如何处理? 非常感谢您。

【问题讨论】:

  • 看看观察者模式,本质上你的线程需要生成你的框架监听的事件,只是要注意swing不是线程安全的
  • 什么是更线程安全的方法?谢谢您的回答。 @MadProgrammer
  • 您只需要注意您的“线程”将在它自己的上下文中生成事件,然后使用SwingUtilities.invokeLaterSwingWorker 之类的东西来确保您对 UI 所做的任何更新都是在事件调度线程的上下文中完成

标签: java multithreading swing thread-safety swingworker


【解决方案1】:

有很多方法可以解决这个问题

用户可以根据需要打开和关闭任意多个 Jframe,并且所有 Jframe 都必须显示从 rs232 读取的相同数据

如果您只对实时结果或历史结果感兴趣,这就提出了一个问题。为了论证起见,我只关注实时结果。

基本上,您需要从一个负责实际从端口读取数据的类开始。这个类应该只做两件事:

  1. 读取数据
  2. 读取新数据时生成事件

为什么?因为您想要实现的任何其他功能(例如将数据写入数据库或出于某种原因缓存结果)都可以稍后添加,只需监控生成的事件即可。

接下来,您需要定义一个interface,它描述了观察者为了能够接收事件而实施的合约

public interface ScaleDataSourceListener {
    public void scaleDataUpdated(ScaleDataSourceEvent evt);
}

您还可以添加连接事件(连接/断开连接)或其他可能很重要的事件,但我保持简单。

ScaleDataSourceEvent 将是一个简单的interface,它描述了事件的数据

public interface ScaleDataSourceEvent {
    public ScaleDataSource getSource();
    public double data();
}

例如(我喜欢接口,它们描述了预期的契约,定义了职责并限制了其他人在收到实现接口的对象的实例时可以做什么,但那是我)

然后,您的数据源将允许观察者注册自己以收到有关它生成的事件的通知...

public interface ScaleDataSource ... {
    //...
    public void addDataSourceListener(ScaleDataSourceListener listener);
    public void removeDataSourceListener(ScaleDataSourceListener listener);
}

(我假设数据源将能够执行其他操作,但我已将其留给您来填写,同样,我更喜欢可能的接口,这不是您的设计限制;) )

因此,当从端口读取数据时,它会生成一个新事件并通知所有注册的侦听器。

现在,Swing 不是线程安全的,这意味着,您不应该从除事件调度线程之外的任何线程更新 UI。

在您的情况下,最简单的解决方案可能是简单地使用 SwingUtilities.invokeLater 从数据源线程上下文移动到 EDT。

基本上,这是一个简单的Observer Pattern

您还需要考虑许多其他注意事项。即,框架是在与数据源相同的进程中打开的,还是数据源在其自己的单独进程中运行。这使过程复杂化,因为您需要某种 IPC 系统,可能使用套接字,但最重要的设计是相同的。

如果数据源读取数据的速度比您生成事件的速度更快,会发生什么情况?您可能需要某种队列,其中数据源只是将数据转储到队列中,并且您有某种调度程序(在另一个线程上)读取它并调度事件。

有多种阻塞队列的实现可以提供一定程度的线程安全,请查看并发 API 以了解更多详细信息。

...作为一些想法;)

【讨论】:

    【解决方案2】:

    首先,创建一个框架类扩展JFrame,并创建一个从rs232接收数据的方法。然后这个类的每个对象都可以使用该方法获取数据。 你可以通过创建一个类的对象来创建一帧。

    【讨论】:

    • 您的答案不正确,因为它没有回答 OP 遇到的基本问题。请将您的答案与 MadProgrammers 进行比较,并检查质量差异。