使Swing组件同步

我正在阅读Java Threads 3rd Ed。 由奥克斯和黄(O’Reilly 2004)。 他们在整本书中都有一个Swing打字游戏的例子。 他们定义的类主要是javax.swing.JComponent自定义子类。

对我来说似乎完全错误的是,他们使用各种同步方法使这些JComponent的线程安全。 我的印象是Swing组件不应该是线程安全的,而是应该始终从Swing事件调度线程访问它们。 (有趣的是,他们通过Swing EDT修改组件的次数之一,它是一个setText ,这是很少有不需要从EDT调用的Swing方法之一。)

我想知道一些在编写/阅读Swing代码方面有很多经验的人:程序员是否常常使Swing组件同步而不是总是通过EDT修改它们? 它可以忍受吗?

编辑:
我注意到它和这个post几乎是同一个问题。 然而,它没有说明程序员在野外实际做了什么。 我很困惑,O’Reilly的书会如此公然违反Swing线程模型。

编辑:
我发现他们在本书的中间部分简要解释了Swing线程模型。 尽管如此,我想回答一下我的问题。 我觉得大多数读过这本书的人最终会违反Swing线程模型,因为他们的大部分例子都是如此。

编辑:
如果要查看代码,可以将示例代码作为zip文件下载 。 例如,参见ch03 / example1 / AnimatedCharacterDisplayCanvas。

编辑:
我刚刚了解到setText在Java7中不是线程安全的(2011年7月发布)。

平凡地说,只要同步方法不在EventQueue上执行,它们就不会阻塞事件派发线程。 相反,在另一个线程上执行的方法应始终使用EventQueue通过invokeLater()invokeAndWait()或相关机制(如javax.swing.Timerjavax.swing.SwingWorker invokeLater()调度代码。 实际上,这些都是可靠的。 这些例子可能是正确的,但应从这个角度来考察它们。

EventQueue API说:“唯一的要求是事件……按照它们排队的顺序发送……” 在我看来,这相当于java.util.concurrent和JLS的“发生在之前”的关系。 可以在此处找到更详细的讨论。

你永远不应该在Swing组件上有同步块,它会在尝试渲染时引起奇怪的问题。

Swing不是线程安全的,因为一切都应该在EDT上更新,甚至创建Swing组件。

应将长时间运行的进程移动到后台线程或SwingWorker。 当EDT以外的线程需要制作组件或对组件进行更新时,应使用SwingUtilities.invokeLater()进行包装。

“Swing组件本质上不是线程安全的,并且作为一般规则,在Swing组件在屏幕上可见之后,您只能从事件线程中安全地修改它们的数据。如果您从除了以外的任何线程修改Swing组件数据事件调度线程,您必须采取预防措施以确保数据完整性。此规则的一个例外是JTextComponent或其任何子类上的setText方法,或其文档明确声明它是线程安全的任何Swing组件方法。 Monica Pawlan http://java.sun.com/developer/technicalArticles/Threads/swing/