简体   繁体   English

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

[英]Is the Swing repaint() method still safe to use outside the EDT in Java 7+?

I know that it used to be considered safe to call repaint() and a few other selected methods from any thread even with Swing's threading model, however I was recently told in a comment that this is not so. 我知道,即使使用Swing的线程模型,从任何线程调用repaint()和其他一些选定的方法也是安全的,但是我最近在评论中告诉我不是这样。

Google found a lot of older discussion saying it is safe but nothing recently. 谷歌发现很多旧的讨论说这是安全的,但最近没什么。 All of the official references that used to say it is safe seem to have disappeared, and I found a few people in various forums discussing how it was no longer safe. 所有过去曾经说过安全的官方参考资料似乎已经消失了,我在各个论坛上发现了一些人讨论它是如何不再安全的。

I cannot find anything official to confirm whether it is or isn't though - and I'd really like to see something explaining the logic of the change if it has been changed. 我找不到任何正式的东西来确认它是否存在 - 而且我真的希望看到一些解释改变逻辑的东西,如果它已被改变的话。 Considering how badly it would risk breaking existing applications it seems like a very odd feature to have removed. 考虑到破坏现有应用程序的风险有多严重,删除它似乎是一个非常奇怪的功能。

Really I'm looking for a link to an official reference (ie Javadoc, oracle tutorial, or source code link) saying whether these methods are or are not still safe to call from any thread. 我真的在寻找一个官方参考链接(即Javadoc,oracle教程或源代码链接),说明这些方法是否可以安全地从任何线程调用。

For reference this question here: 这里提到这个问题:

Safe to use Component.repaint() outside EDT? 在EDT之外安全使用Component.repaint()?

Gives a quote from a now disappeared Sun page saying: 从现已消失的Sun页面中引用一句话:

The following JComponent methods are safe to call from any thread: repaint(), revalidate(), and invalidate(). 以下JComponent方法可以安全地从任何线程调用:repaint(),revalidate()和invalidate()。 The repaint() and revalidate() methods queue requests for the event-dispatching thread to call paint() and validate(), respectively. repaint()和revalidate()方法将事件派发线程的请求分别调用paint()和validate()。

That matches to my understanding, but I cannot find that page or any similar page now and I have seen unconfirmed rumours from several people saying it is no longer safe. 这符合我的理解,但我现在找不到那个页面或任何类似的页面,我看到几个人的未经证实的谣言说它不再安全。 But on the other hand I can find nothing definitive saying that this feature has changed. 但另一方面,我找不到任何明确的说这个功能已经改变。

Change notes 改变笔记

What may help solve this question is an official statement from Oracle about the changes in Swing thread handling. 可能有助于解决这个问题的是Oracle关于Swing线程处理变化的官方声明。 I found the "changes in Java 7" page but that didn't mention it at all, neither of these pages mention threading or the EDT in any way: 我发现了“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/swing/enhancements-7.html

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

This is the official reference : 这是官方参考

Swing's Threading Policy Swing的线程策略

In general Swing is not thread safe. 一般来说,Swing不是线程安全的。 All Swing components and related classes, unless otherwise documented, must be accessed on the event dispatching thread. 除非另有说明,否则必须在事件派发线程上访问所有Swing组件和相关类。

And the repaint method does not "document otherwise". 并且repaint方法不会“以其他方式记录”。

To doubly reassure you that you do not need to look any further than an individual method's Javadoc for the definitive answer, see for example how a method's thread safety was documented in Java 6 Javadoc . 为了让您更加放心,除了单个方法的Javadoc之外,您不需要进一步了解最终答案,例如,请参阅Java 6 Javadoc中如何记录方法的线程安全性。

Update 更新

Apparently, more clarification is needed as to the distinction between normative specification, descriptive technical articles, and details of any specific implementation. 显然,需要对规范性规范,描述性技术文章和任何具体实现的细节之间的区别进行更多澄清。 What the Javadoc states is this: there is no guarantee that repaint is a thread-safe method . Javadoc所说的是: 不能保证repaint是一种线程安全的方法 Incidentally, the often-discussed decision in Java 7 to remove the "thread-safe" designation from most of the Swing API was just that: a change in contract , not implementation. 顺便提一下,Java 7中经常讨论的从大多数Swing API中删除“线程安全”标识的决定就是: 合同的变更,而不是实现。

The specific implementation of repaint in OpenJDK 7 appears to be thread-safe, a fact which has nothing to do with guarantees given by the specification. OpenJDK 7中repaint的具体实现似乎是线程安全的,这与规范给出的保证无关。 Code which relies on the thread safety of repaint or other methods is broken and is not guaranteed to behave properly on all Java implementations. 依赖于repaint或其他方法的线程安全性的代码被破坏 ,并且不能保证在所有Java实现上都能正常运行。

As discussed in Painting in AWT and Swing: Paint Processing , 正如在AWT和Swing绘画中所讨论的:油漆处理

JComponent.repaint() registers an asynchronous repaint request to the component's RepaintManager , which uses invokeLater() to queue a Runnable to later process the request on the event dispatching thread. JComponent.repaint()向组件的RepaintManager注册异步重绘请求,该组件使用invokeLater()Runnable进行排队,以便稍后在事件派发线程上处理请求。

This is a necessary, but not sufficient, condition to establish a happens-before relation between successive calls to repaint() . 这是在连续调用repaint()之间建立先发生关系的必要条件,但不是充分条件。 As a practical matter, you still need to synchronize access to any data that is shared between threads. 实际上,您仍然需要同步访问线程之间共享的任何数据。 Without this, there's no way to ensure the visibility of any changes meant to influence the subsequent call to repaint() . 如果没有这个,就无法确保任何可能影响后续调用repaint()更改的可见性。

I would say it is still thread safe. 我会说它仍然是线程安全的。 The repaint() method doesn't change the property of any Swing component. repaint()方法不会更改任何Swing组件的属性。

The repaint() method invokes the RepaintManager. repaint()方法调用RepaintManager。 The RepaintManager will then (potentially) combine multiple painting requests into a single paint request. 然后,RepaintManager将(可能)将多个绘制请求组合到一个绘制请求中。 It will then add the paint request to the EDT for processing. 然后它会将油漆请求添加到EDT进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM