0

Before I go on discussing the basic query I would first like to state that I am fully aware of my question being against the standards of the AWT/Swing framework. My query is meant merely as a academic experience and should (hopefully) never be applied to real world applications.

The AWT/Swing framework is built upon a event based model which uses a single thread to dispatch events. All AWT/Swing related events events must be processed on the Event Dispatcher Thread (EDT) and any custom events that the programmer has programmed must be queued through the functions invokeAndWait() and invokeLater(). While this model ensures that the framework never suffers from any sort of thread concurrency issues it gives a big pain to programmers trying to write code around it (search swing issues on stackoverflow... quite a handful).

However... Years ago, before I got more familiar with the AWT/Swing model and the EDT I used to write code that violates many many java standards (code that'll make any reasonable programmer recoil in horror). One of these standards I violated was calling methods that updated the GUI through a thread thats not the EDT. To be precise it was a standard "long" task that resided on a secondary thread which periodically updated a JLabel with the current progress. Reviewing the code now I realized that despite the fact that the code directly violated the standard, it worked 100% of the time. I noticed no flickering, no corruption of text (since it was a JLabel), no random exceptions being thrown and no abnormal GUI behavior. Of course I know from one tiny example, one cannot simply determine the AWT/Swing standards are over-protective or unnecessary. And with this, my query lies:

For simple tasks like updating a JLabel (not even at a constant rate, maybe once or twice a second) is it truly necessary to perform it through the EDT? And what are the possible implications (apart from being despised by the whole java programming community) of this (I want a list of solid implications, not just "it might cause the EDT to mess up")?

Assume a model where only one thread updates the GUI (which is not the EDT) and the updates are infrequent and only update in atomic operations (updating strings, primitive data, etc) is it possible that the program can run free of problems caused by the EDT (I guess this counts as a hack?).

As a challenge, I was wondering if its possible anyone can come up with code that demonstrates a violation of the AWT/Swing model by dispatching events from another thread causing obvious and constant (as in I don't have to wait 2 hours for the GUI to flicker for 1 frame) problems?

And by the way, this might be unrelated but does a new EDT thread spawn for a new JFrame/Window object or do all of them run off the same thread? I can't imagine a resource-heavy multi-window system all running off one thread.

NB: I have never seen nor analyzed the source code of the AWT/Swing framework and all my knowledge is based on internet research and personal experience. If there is any mistake above, please feel free to correct me. For those programmers still in shock from my example above, I have updated all my projects to comply to the standard (what a pain).

initramfs
  • 8,275
  • 2
  • 36
  • 58
  • Note that in JavaFX you would get an exception if you update your label from another thread. They did not make the same mistake as in Swing to only document to use a single thread, but really enforced it. Reading [this question](http://stackoverflow.com/q/5544447/1076463) might also be a good idea – Robin Jul 31 '13 at 19:50
  • 2
    It is not unusual that code violating the threading rules appears to work. But the more places you do it the more probable it becomes that you get graphical errors somewhere. It is also fairly typical that the same program may appear to work correctly on one system, but is buggy on another, or on different jvm version. – kiheru Jul 31 '13 at 19:51
  • @kiheru I am aware of that... But the difference is that the code "practically works"... that particular program was distributed to most major operating systems (by me... it was a personal program) and all of them exhibited no odd behavior. (Tested on WinXp/7/8, Mac OS X/Arch Linux/Ubuntu with Java 6 ~ Java 7). I know its still not right to fail protocol, my question is is the protocol necessary given the right circumstances. – initramfs Jul 31 '13 at 20:01
  • @downvoter Mind informing me on why this is a bad question? – initramfs Aug 01 '13 at 08:58
  • this question is rather useless, especially if you keep repeating anecdotical "evidence" ;-) Yeah, you can get away with breaking the rules, how cool is that ... If you are so keen on finding an actual breakage, just read up on general threading problems and try to drive some ui into exhibiting such problems. It's a waste of time, even if it were possible (don't know) - because it's the _other_ way round that matters: a gui must be as correct, robust, maintainable as any other application. Knowingly implementing bugs doesn't help in that goal. – kleopatra Aug 01 '13 at 09:04
  • @kleopatra If you read my first statement... I have already said that I would never implement this in actual code. The goal of this question is if it was theoretically possible to bypass the EDT and if not why not. Since everyone is so keen on saying its not possible, a reason (other than because the documentation says so) would be nice. – initramfs Aug 01 '13 at 10:29

1 Answers1

3

An example of where this fails: Set your JLabel to be right-aligned. Then drawing requires two steps - measuring the text, in order to calculate the position, and then drawing it. If you change the text while it is painting (say, due to an animation loop) the text will seem to jump occasionally.

In answer to your other question - there is only one EDT, for all GUI components.

Example of "constant and obvious" change: Suppose the JLabel has HTML content. In your background thread, after the text is set and a repaint is fired, a PropertyChange is also fired, which causes the UI delegate to reparse the HTML and set it in a client property (working in the background thread, although the UI assumes it is in the EDT because it is receiving an event).

So now you have a race condition: If the UI repaints the label (in the EDT) before it finishes calculating the HTML view in the background thread, it will paint the old HTML and your label will appear to not update.

You could say, "Well then, I just won't use HTML in my label." But the point is that situations like this are pervasive in the Swing libraries - a strong assumption is made everywhere that events are passed only on the EDT, and without reading a huge amount of the Swing source you can't guarantee that you won't run into a problem like this.

Russell Zahniser
  • 16,188
  • 39
  • 30
  • Can you provide code that can demonstrate this? And also, if thats all the EDT protects from, the example given above (where updates happen infrequently) should be completely risk free (or the possibility of a glitch be so remote it shouldn't be considered) – initramfs Jul 31 '13 at 20:03
  • +1 hmmm there is only one EDT, for all GUI components. != true :-) in Java7 is there [SecondaryLoop](http://docs.oracle.com/javase/7/docs/api/java/awt/SecondaryLoop.html), true is I can't found some real usage of, could be an alternative, to [avoiding usage of eventQueue.push()](http://stackoverflow.com/a/3158409/714968) – mKorbel Jul 31 '13 at 20:23
  • @mKorbel: With `SecondaryLoop` there is still only the single EDT - what it does is to run the event pump manually from within `enter()`, until `exit()` is called, so that `enter()` seems to "block" like showing a modal dialog. – Russell Zahniser Jul 31 '13 at 20:29
  • @CPUTerminator It is really difficult to make a sample that would *consistently* provide broken behaviour, race conditions being notoriously difficult to reproduce. While the particular example may no be dangerous, what if the label that failed to update is the name of a table going to be dropped and waiting for user confirmation? – kiheru Jul 31 '13 at 20:30
  • @kiheru I understand the indirect implications may be severe, thats why I stated I would never do that in real world applications. However, if the conditions where right shouldn't there by a 0% chance that the update itself will fail (or have a similar failure rate to complying to the AWT/Swing standards). And yes... I know its difficult if not impossible to make code that will fail consistently, thats why I wrote "As a challenge" :) – initramfs Jul 31 '13 at 20:54
  • @RussellZahniser In response to your edit... I see your point now... and thus I shall fall back to my most basic query: Given the right circumstances, is it necessary to use the EDT (Like you said, no big chunks of HTML. A awful lot of programmers actually just want to do simple updates to the GUI without having to type 3-4 extra lines instead of one function/method call). Your comment on "without reading a huge amount of the Swing source" is exactly what I hoped someone had done before and answered this question. :) – initramfs Jul 31 '13 at 21:11
  • @CPUTerminator _is it necessary to use the EDT_ how often do you intend to repeat that question? The answer wouldn't change: it's **YES, YES, YES** whatever the circumstances (except when you want to torpede the quality of your application right from the start ;) – kleopatra Aug 01 '13 at 09:08
  • 1
    @kleopatra I know this... my question is not "when can you not use the EDT". Its given the above circumstances, is it theoretically okay to bypass the EDT and if not what problems may occur. I see no race condition or concurrent modification in my example above. The key is theoretically... I'm not intending to find places where I can bypass the EDT but rather learn more about its underlying mechanics. If your answer is "YES YES YES" is this answer based solely on the documentation or do you have some further knowledge on why it may cause problems and/or what problems it may cause? – initramfs Aug 01 '13 at 09:37