在 Java 7+ 中的 EDT 之外使用 Swing repaint() 方法是否仍然安全?

我知道,即使使用Swing的线程模型,调用和从任何线程中选择的其他一些方法也被认为是安全的,但是我最近在评论中被告知事实并非如此。repaint()

谷歌发现了很多较旧的讨论,说它是安全的,但最近什么都没有。所有曾经说它是安全的官方参考资料似乎已经消失了,我在各种论坛上发现一些人在讨论它如何不再安全。

我找不到任何官方的东西来确认它是否是 - 如果它已经被更改,我真的希望看到一些东西来解释更改的逻辑。考虑到破坏现有应用程序的风险有多大,删除它似乎是一个非常奇怪的功能。

实际上,我正在寻找一个指向官方参考(即Javadoc,oracle教程或源代码链接)的链接,说明这些方法是否仍然可以从任何线程调用。

有关参考,请点击此处查看以下问题:

在EDT之外使用Computicter.repaint()安全吗?

引用现已消失的太阳页面的一句话说:

以下 JComponent 方法可以从任何线程中安全调用:repaint()、revalidate() 和 invalidate()。repaint() 和 realidate() 方法将事件调度线程的请求排队,分别调用 paint() 和 validate()。

这与我的理解相符,但我现在找不到该页面或任何类似页面,并且我看到了几个人未经证实的谣言,说它不再安全。但另一方面,我找不到任何明确的说法,即此功能已更改。

更改说明

可能有助于解决这个问题的是Oracle关于Swing线程处理变化的官方声明。我找到了“Java 7中的更改”页面,但根本没有提到它,这些页面都没有提到线程或EDT:

http://docs.oracle.com/javase/7/docs/technotes/guides/swing/enhancements-7.html

http://docs.oracle.com/javase/7/docs/technotes/guides/awt/enhancements-7.html


答案 1

这是官方参考

Swing 的线程策略

一般来说,Swing不是线程安全的。除非另有说明,否则必须在事件调度线程上访问所有 Swing 组件和相关类。

并且该方法不会“以其他方式记录”。repaint

为了加倍向您保证,您不需要再查看单个方法的Javadoc以获取明确的答案,例如,请参阅Java 6 Javadoc中如何记录方法的线程安全性。

更新

显然,需要进一步澄清规范性规范、描述性技术条款和任何具体实现细节之间的区别。Javadoc声明的是:不能保证重绘是线程安全的方法。顺便说一句,在 Java 7 中经常讨论的从大多数 Swing API 中删除“线程安全”名称的决定只是:契约的更改,而不是实现。

OpenJDK 7 中的具体实现似乎是线程安全的,这一事实与规范给出的保证无关。依赖于线程安全或其他方法的代码被破坏,并且不能保证在所有Java实现上都能正常运行。repaintrepaint


答案 2

正如在AWT和秋千中的绘画:油漆加工中所讨论的,

JComponent.repaint()将异步重绘请求注册到组件的 ,该请求用于将 a 排队以便稍后在事件调度线程上处理请求。RepaintManagerinvokeLater()Runnable

这是在对 的连续调用之间建立先发生关系的必要条件,但不是充分条件。实际上,您仍然需要同步对线程之间共享的任何数据的访问。否则,就无法确保任何旨在影响后续调用 的更改的可见性。repaint()repaint()