【问题标题】:Is it OK to change a model outside the Swing worker thread?可以在 Swing 工作线程之外更改模型吗?
【发布时间】:2010-12-23 04:06:22
【问题描述】:

在“严肃”的 Java GUI 应用程序中,许多 GUI 元素背后都有模型:例如,DocumentModel 支持JEditorPane,或者ListModel 支持JList

我们总是被告知不要从 Swing 工作线程之外进行 GUI 更改,并给予 SwingUtilities.invoke...() 以解决该问题。好吧,我可以忍受!当直接更改 GUI 组件的属性时,这当然是必要的(并且效果很好)。

理想情况下,我的大部分 GUI 可见更改将针对模型,而不是针对 JComponents。但是因为它们是 GUI 可见的,所以它们是否“算”为 GUI 更改? IE。更改事件和侦听器是否提供了必要的解耦,或者模型更改是否也需要包含在 invoke...() 中?

可能是 Swing 专业人士的老帽子,但我找不到任何明确说明这种或另一种方式的参考资料。

【问题讨论】:

    标签: java user-interface swing concurrency


    【解决方案1】:

    如果事件从 EDT 触发并更新 Swing 组件,这将是一个问题。

    在 Swing 文本中,事件可能会或可能不会(!)传输到 EDT。这使测试变得棘手。不出所料,该 API 在多线程环境中没有用处。

    所以:最容易将模型保留在 EDT 上,其他线程应该传递消息(涉及 EventQueue.invokeLater)。或者,您可以对所有内容进行大锁定,这更加困难(并且您可能仍需要将内容传递给 EDT)。尝试微同步非常困难。

    【讨论】:

    • “微同步非常困难。” : 我完全同意这一点。我删除了所有同步的关键字,并更仔细地检查了对 GUI(以及 GUI 元素的模型)的每次修改都是在 EDT 上完成的。
    • 我害怕这个。这意味着我的模型在技术上成为 GUI 的一部分,并且为此目的必须被视为 GUI 的一部分。从分层/封装的角度来看,它似乎并不“干净”,而且(当然,这是我最大的反对意见)它需要更多的工作! +1,谢谢!
    【解决方案2】:

    通常,模型更改必须包装到invokeLater(...) 中。我查看的大多数 Swing 类的模型代码中都没有解耦。

    由您来创建一个模型,该模型可以包含检查是否在事件调度线程上进行 GUI 修改的调用。

    【讨论】:

    • -1:不是我想听到的答案! (开个玩笑,+1)谢谢!
    • 关于 Swing 线程问题调试,我强烈推荐这个链接:weblogs.java.net/blog/alexfromsun/archive/2006/02/… CheckThreadViolationRepaintManager 为我节省了很多时间。
    • Swing 文本会一些将事件转移到 EDT。当然,这只会造成更大的混乱。
    • 对于所有 Swing 组件和相关模型,您必须假设它们必须在 GUI 线程上调用 - 除非他们的文档明确声明您不这样做。一些组件/模型具有同步方法,您可以从不同的线程进行修改,但大多数没有。
    【解决方案3】:

    是的,绝对没问题。

    虽然确实不应该在 EDT 之外修改 Swing 组件。您当然可以在 EDT 之外更改他们的模型。

    如果您已将模型正确连接到 Swing 组件,则视图更新和 EDT 调度将几乎自动发生。

    见:http://java.sun.com/products/jfc/tsc/articles/architecture/#roots

    参见JavaBeans事件模型部分。

    这就是模型以 EDT 安全的方式将其更改的状态传达给 GUI 的方式。在创建新的 GUI 组件时,您应该遵循这种设计模式。

    还要注意 GUI 状态模型和应用程序数据模型之间的区别。

    从 EDT 更改模型仍然需要小心。事实上,大多数 Swing 问题发生在程序员在 EDT 中修改模型时,而他们应该从单独的线程中修改它。 (臭名昭著的冻结 GUI 问题)

    这也不排除完全意识到典型的多线程陷阱。

    但您绝对可以从 EDT 外部对 JTableModel 进行更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 2021-03-20
      • 1970-01-01
      相关资源
      最近更新 更多