Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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 (i.e. Javadoc, oracle tutorial, or source code link) saying whether these methods are or are not still safe to call from any thread.

For reference this question here:

Safe to use Component.repaint() outside EDT?

Gives a quote from a now disappeared Sun page saying:

The following JComponent methods are safe to call from any thread: repaint(), revalidate(), and invalidate(). The repaint() and revalidate() methods queue requests for the event-dispatching thread to call paint() and validate(), respectively.

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. 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:

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

like image 841
Tim B Avatar asked Jan 03 '14 14:01

Tim B


2 Answers

This is the official reference:

Swing's Threading Policy

In general Swing is not thread safe. All Swing components and related classes, unless otherwise documented, must be accessed on the event dispatching thread.

And the repaint method does not "document otherwise".

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.

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. 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.

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. 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.

like image 116
Marko Topolnik Avatar answered Oct 16 '22 11:10

Marko Topolnik


As discussed in Painting in AWT and Swing: Paint Processing,

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.

This is a necessary, but not sufficient, condition to establish a happens-before relation between successive calls to 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().

like image 27
trashgod Avatar answered Oct 16 '22 09:10

trashgod