使Swing组件同步

时间:2011-06-22 19:05:35

标签: java multithreading swing

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

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

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

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

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

修改
如果您想查看代码,可以Download examples code作为zip文件。参见例如ch03 / example1 / AnimatedCharacterDisplayCanvas。

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

3 个答案:

答案 0 :(得分:2)

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

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

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

进行包装。

答案 1 :(得分:2)

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

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

答案 2 :(得分:-1)

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