Should non-Swing code be executed on non-EDT threads? - java

I know the Swing single-thread rule (from Java Concurrency in Practice):
Swing components and models should be created, modified, and queried
only from the event-dispatching thread.
Is the converse also true? I maintain some transaction logging code that writes event information to a file and it sometimes does this on the EDT. Is this a bad practice?

That depends on what you are doing. Basically while you are using the EDT thread then it cannot do anything else. That means button clicks, processing, user interface updates, etc will all be stalled.
So for long-running tasks you should use a different thread (for example SwingWorker) but for anything that is unlikely to stall or take a long time doing it on the EDT is fine.

Related

Differences between Java's SwingWorker and Android AsyncTask

I was comparing the differences between Swing's SwingWorker and Android's AsyncTask classes. While Android has a Main Thread/UI Thread and then spawns a background thread (using AsyncTask), SwingWorker has three threads that are involved -
Current thread
Worker thread
Event Dispatch Thread.
And then I also came across the statement (in docs) -
Often, the Current thread is the Event Dispatch Thread.
Now, what does this mean?
Does it mean that Swing also has only 1 thread - the Main Thread and
even the events are received on the same thread OR
Is it different for different JVM implementations?
This is only valid for Swing, which shares some similarities with Android UI programming but is indeed not the same.
A little bit of context
The EDT (Event Dispatch Thread) is Swing's thread dedicated to handling UI events (mouse and keyboard input, events on controls, rendering of the UI, etc...).
This is an Event Loop model, similar to what is done in Android.
The fact that event listeners in Swing are executed on the EDT is the root cause for freezing UIs in Swing applications: developers misunderstanding the threading model often put long-running code in the listeners, which blocks the EDT and thus the GUI.
SwingWorker was introduced to better guide developers in separating UI updates from long-running background code. It spawns a dedicated background thread for the I/O processing (or long-running task) in doInBackground and executes UI updates in done and process methods. While these 3 methods guarantee in which thread they'll be executed, all other methods are executed in the current thread.
What is meant by the sentence you quoted
The whole reason for SwingWorker to exist is to properly initiate a long-running process from the GUI, without blocking the GUI.
Often, it will be in reaction to a user's input (e.g. clicking a Button). Since reactions to the user's input (implemented as Listeners) are always executed in the EDT by the Swing framework, unless you happen to call execute or get from another thread explicitly, it will get executed on the EDT.
By the way, execute is "fire-and-forget" and is the typical use-case (call it from a listener). get on the other hand blocks, and is not suited to be called from a listener (it would defeat SwingWorker's purpose, call it on your own threads if needed)!

event dispatch thread [duplicate]

I know what "thread" means and if I understand the event dispatching thread (EDT) as
"just a thread", it explains a lot but, apparently, it does not explain everything.
I do not understand what is special about this thread. For example I do not understand why we should start a GUI in a the EDT? Why the "main" thread is bed for GUI? Well, if we just do not want to occupy the main thread why we cannot start GUI just in "another thread" why it should be some "special" thread called EDT?
Then I do not understand why we cannot start the EDT like any other thread? Why we should use some special tool (called invokeLater). And why GUI, unlike any other thread, does not start immediately. We should wait until it is ready to accept our job. Is it because EDT can, potentially execute several task simultaneously?
If you decide to answer this question, could you pleas use a really simple terminology because otherwise, I am afraid, I will not be able to understand the answer.
ADDED:
I always thought that we have one "task" per thread. So, in every thread we execute a predefined sequence of commands. But it seems to me that in the event dispatching thread we can have sever task. Well, they are not executed simultaneously (thread switches between different task but there are still several task in one thread). Is it right? For example there is one thread in the EDT which display the main window, and then additionally to that we sent to the EDT another task which should update one of the window components and EDT will execute this new task whenever it is ready. Is EDT differ from other threads in this way?
The event dispatching thread is the thread that handles all GUI events and manages your Swing GUI. It is started somewhere in the Swing code if you have any GUI in your program. The reason it is done behind the scenes is because of simplicity - you do not have to bother with starting and managing an extra thread by yourself.
Regarding the fact that you have to update your GUI with invokeLater() it is because of concurrency issues. The GUI can be modified only from one thread because Swing is not thread safe(it is worth to note that most of toolkits are not thread safe, there is a nice article that gives some ideas why). This is why you have to submit all GUI updates to run on EDT.
You can read more on concurrency in Swing and event dispatching thread in Sun tutorial on concurrency in Swing. Also, if you would like to see how this could be done in a different way you might like to check out SWT toolkit. In SWT you have to manage EDT by yourself.
I always thought that we have one
"task" per thread. So, in every thread
we execute a predefined sequence of
commands. But it seems to me that in
the event dispatching thread we can
have sever task. Well, they are not
executed simultaneously (thread
switches between different task but
there are still several task in one
thread). Is it right? For example
there is one thread in the EDT which
display the main window, and then
additionally to that we sent to the
EDT another task which should update
one of the window components and EDT
will execute this new task whenever it
is ready. Is EDT differ from other
threads in this way?
No, the EDT is not fundamentally different from other threads. And "task" is not a good word to use, because it could be confused with OS-level processes (which are also often called task). Better use Runnable, the interface used to give code to the EDT to execute via invokeLater().
The EDT is basically connected to a queue of things it has to do. When the user clicks a button on the GUI, a Runnable that notifies all listeners attached to the button goes into the queue. When a window is resized, a Runnable doing revalidate&repaint goes into the queue. And when you use invokeLater(), your Runnable goes into the queue.
The EDT simply runs an endless loop that says "take a Runnable from the queue (and if it's empty sleep until you're notified that it's not) and execute it.
Thus, it executes all those little Runnable pieces of code one after another, so that each of them basically has the GUI all to itself while it runs, and doesn't have to worry about synchronizing anything. When you manipulate the GUI from another thread, this assumption is broken, and you can end up with the GUI in a corrupted state.
What is the EDT?
It's a hacky workaround around the great many concurrency issues that the Swing API has ;)
Seriously, a lot of Swing components are not "thread safe" (some famous programmers went as far as calling Swing "thread hostile"). By having a unique thread where all updates are made to this thread-hostile components you're dodging a lot of potential concurrency issues. In addition to that, you're also guaranteed that it shall run the Runnable that you pass through it using invokeLater in a sequential order.
Note that it's not just that you're dodging the concurrency issue: you must respect Sun's guidelines regarding what must and what must not be done on the EDT or you'll have serious problems in your application.
Another benefit is that some Swing components tend to throw unwanted exceptions and when this happen they're automagically dealt with and won't crash the EDT (AFAIK if you really manage to kill the EDT it is automagically restarted).
In other words: you don't have to deal with all the broken Swing components and the exceptions they throw yourself: the EDT is taking care of that (just take a look at the countless Swing bugs throwing exceptions in Sun's bug parade, it's fascinating... And yet most apps keep working normally).
Also, by doing only what's mandatory in the EDT allows the GUI of your app to stay "responsive" even tough there may be tasks running in the background.
The important thing to remember is that Swing classes are not thread-safe. This means that you always should call Swing methods from the same thread, or you risk getting weird or undefined behavior.
So the solution: only call Swing methods from a single thread. This is the EDT thread - it's not special in any way other than that it is the thread designated to call swing methods from.
Now you may ask why are Swing methods not thread safe? After several unsuccessful attempts, GUI toolkit designers discovered that it's inherently impossible to design a thread-safe GUI toolkit. Too often events are passed in opposite directions (input events from bottom to top, application events from top to bottom) which always leads to deadlocks. So that's just the way it is.

Why SwingWorker? Why not just Thread or Runnable?

What are the advantages of using SwingWorker instead of Thread or Runnable?
I think the documentation of the SwingWorker is pretty good:
An abstract class to perform lengthy
GUI-interacting tasks in a dedicated
thread.
When writing a multi-threaded
application using Swing, there are two
constraints to keep in mind: (refer to
How to Use Threads for more details):
Time-consuming tasks should not be run on the Event Dispatch Thread.
Otherwise the application becomes
unresponsive.
Swing components should be accessed on the Event Dispatch Thread
only.
These constraints mean that a GUI
application with time intensive
computing needs at least two threads:
1) a thread to perform the lengthy
task and 2) the Event Dispatch Thread
(EDT) for all GUI-related activities.
This involves inter-thread
communication which can be tricky to
implement.
SwingWorker is designed for situations
where you need to have a long running
task run in a background thread and
provide updates to the UI either when
done, or while processing. Subclasses
of SwingWorker must implement the
doInBackground() method to perform the
background computation.
surely you can do this using Thread, Runtime and SwingUtilities (invokeLater) but it's easier and probably less error prone using the SwingWorker class.
Thread and Runnable were part of Java 1.0; they're as good as they were back then.
The new concurrency classes distill all that's been learned about multi-threading since then (thank you, Doug Lea and others). Writing multi-threaded code is terribly difficult. The new concurrency classes, including SwingWorker, try to make that easier.
Start by noting the generics for strong typing. There's a mechanism built in to publish and process both final and intermediate results.
It'd be possible to mimic these with Thread and Runnable, but SwingWorker has done it for you.
SwingWorker takes care of some details, like UI updates while running the task, or after task finishes. These must be executed on Swing EDT thread. You can do it yourself, but it's too easy to do it wrong.
SwingWorker encapsulates correct interaction with the event dispatching thread. Runnable doesn't.

SwingUtilities.invokeLater() why is it needed?

Why is it necessary to put GUI update code in SwingUtilities.invokeLater()?
Why cant it be internally taken care of by Swing itself? Why does the caller have to care about how swing handles UI updates?
Swing objects are not thread safe. SwingUtilities.invokeLater() allows a task to be executed at some later point in time, as the name suggests; but more importantly, the task will be executed on the AWT event dispatch thread. When using invokeLater, the task is executed asynchronously; there's also invokeAndWait, which won't return until the task has finished executing.
Some information about the decision not to make Swing thread-safe can be found here: Multithreaded toolkits: A failed dream? [Archived]
Because GUI updates must be done in the event dispatch thread. If you're operating in a different thread, doing the update in invokeLater yanks it out of your thread and into the event thread.
More explanation here: http://www.oracle.com/technetwork/java/painting-140037.html
The smart thing to do with big updates (like repopulating a JTable from the database) on Swing is to get the underlying model, do the updates on the model in your thread, then fire off a notification using invokeLater. That keeps your gui responding to events and redrawing. If the update is going to be very extensive, you can even fire off these notifications with invokeLater at regular intervals while you're updating, like every second or two.
Swing is single-threaded. Every update to the UI must happen from the so-called EDT – the event-dispather thread which is the main GUI thread Swing (and I think AWT) uses. If you don't do this, then weird things can or will happen (though I like Windows Forms better here which just throws an exception if you do it wrong).
That being said, you don't need to wrap every single UI operation into SwingUtilities.invokeLater() – if the code you're writing is already executed by the EDT this isn't needed. So the ActionListener for a button click doesn't need this. But a listener on an external object, running in some other thread, that updates a JLabel somewhere – there you need it.
Swing was not written to be a thread safe GUI toolkit so all GUI updates should happen from a single thread to avoid any deadlocks. In Swing this is the Event Dispatcher Thread (EDT).
See Concurrent in Swing from the Java tutorial for more details. It also references this blog entry on why it is hard to write a multithreaded GUI toolkit.
All the painting of the components should be performed in a single thread, so, they are rendered properly. That way the component will know, what part has already been painted and which part hasn't.
If you invoke a "painting" related method ( paint, update, paintComponent, show, setVisible, pack etc. ) outside the EDT, you'll be trying to paint in two different threads, and that may bring problems.
When you need to use another thread to update the UI, you should invoke it with the invokeLater facility, which in turn will put it in the EDT for you, so you still paint in the same thread.
You don't need to use it, if you're coding in a method that runs in the EDT already ( for instance, actionPerformed or paint or one of those ) Or if you are executing code not UI related ( for instance, processing files in the background etc. )
To better understand all these concepts read:The single thread rule
SwingUtilities.invokeLater()
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI.
...
Repeating others: Swing is not thread safe so one thread must do all the updates to avoid concurrency problems. invokeLater is an utility method to execute something inside the event processing thread.
Why doesn't Swing does it internally: this is my impression... I think because it would be overkill -to check every place where an update is taking place. It would bloat the Swing code, dificult the review and maintainability of the code.
By the other hand it's not that dificult for an application to know if it's not executing inside the GUI thread and call invokeLater. It will be when the own application launched some thread before.

What happens when Swing's threading policy is violated?

In the past few years I've mostly done UI development in Eclipse, which is very conservative in terms of thread access: any attempt to change a property on a UI widget (e.g., color, text) from outside the UI thread throws an exception.
I am now looking at an existing program in Swing that has a window with a large number of custom widget. There is a separate threads that runs a mutation function for each of these widgets, and the mutation function reads the value of some things (e.g., label colors and values) and writes some (e.g., changes background colors). Note that there is no custom painting involved or anything like that, just a bunch of changes to the sub widgets it contains which are mostly JLabels.
At present, this runs from the separate thread, not from the Swing event thread. This thread goes over all the 400 widgets and calls the mutator on each. The updates seem to work correctly, but the GUI is unresponsive to user input.
If I take the whole thing, which runs for about 0.4 msec from outside the Swing thread and wrap every call to a mutator in an invokeLater or invokeAndWait, the UI is a lot more responsive.
What I'm trying to understand is:
1) Is it sometimes legitimate to make all these calls from outside the Swing thread?
2) What is the impact on the Swing thread and why is the UI less responsive when I call it from outside?
From "Nothing" to intermittent problems to "Everything Broke, pull everyone off to work on the GUI!"
The main (most obvious) visual effect is that if you hold up the GUI thread (like someone presses a button and you do a sleep(5000) or something), your GUI won't repaint. It can't because you are holding onto the only thread it's allowed to pass you! This makes people think Java is really slow. It's not bad, but it's easy enough to program that a lot of people who don't bother researching practices like this have produced shipping products.
The next biggest problem is that when you are drawing the screen in another thread (like the one passed to main), it can have strange behavior. Swing is already too picky about how you render your frames--take out threading as a variable!
Finally, rarely (or often if you are calling a swing component in a tight loop on the wrong thread) you can get thread collisions. If that happens an exception may be thrown (or not) and something will probably render wrong, but it may not be obvious.
1) Is it sometimes legitimate to make all these calls from outside the Swing thread?
There are a few exceptions (setting the text value of a text field, for example, does automatic EDT proxying for you) - but there are no situations where it is better to do so. If you are performing lots of updates, you can do them all in a single EDT call (a single call to invokeLater()) instead of individual calls - but even that sort of batching very rarely helps things. Long and short: Perform operations on Swing components from the EDT. That includes reads and writes.
2) What is the impact on the Swing thread and why is the UI less responsive when I call it from outside?
Well, the EDT is responsible for updating the GUI. If you call from outside, it isn't 'less responsive' - it's that the actual low level system calls that update the user interface don't occur (at all). What is probably happening in your app is that the original developers are getting lucky and changing state in the swing component without creating a really nasty race condition. Then some other event is causing a repaint to occur on the EDT, which results in the component being updated. This may appear to be a 'lack of responsiveness' - but what's really happening is a 'lack of screen refresh'.
The EDT is just a regular thread, but it is a bit special in that it runs in a tight loop that processes GUI related signals (draw commands, for example). The semantecs of posting these types of commands on the EDT is really, really different from what we typically think of as Java threading (it involves submitting operations to a message pump).
Long and short - all those Javadocs that say 'only interact with Swing objects on the EDT' are written for a reason. Don't mess with it. If you want to do background processing, fine - but you are responsible for proxying the interaction with the J* components back onto the EDT (most generally using invokeLater() ).
There really are no exceptions. Kevin is partially correct - the JTextComponent.setText() is advertised as thread safe. However, looking at the 1.6 code, it provides synchronization on the document object and does not use the EDT. This is fine, unless another swing component (or something that controls swing components) is listening to the document object. Save yourself the trouble of worrying about it, and just always use the EDT - like Kevin says, there really are no situations (that I'm aware of) to do otherwise.
Hard to say without digging into the code; the behavior is undefined. If your background tasks were long running (> a few seconds), you'd see the opposite effect - using the EDT will make the UI unresponsive while your tasks are running.
Fortunately, it sounds like doing it the right way is working best for you anyway. :)
Sun used to say it was ok to use other threads with components that haven't been realized, but later recanted:
Related stackoverflow question
Check out Sun's UI tutorial on swing and concurrency (I'd post the link, but this is my first answer on stackoverflow0.
The basic problem is that non-thread-safe objects are executed in a multithreaded fashion. Even something as simple as reading a HashMap can be caught in an infinite loop. Because AWT uses locks (badly), you can also end up with deadlocks. However, you are likely to get away with it, although you might find that an updated version of Java suddenly causes you issues on some customer machines.
(BTW: It's AWT's Event Dispatch Thread, not Swing's.)
For (1) as a rule of thumb anything that updates pixels on screen must be called from the Event Dispatching Thread (EDT). Where some JVMs may handle updates from outside the EDT acceptably you should never rely on this working, some machines and different look and feels will not work acceptably. The behaviour is undefined - and this could explain the lack of responsiveness you have seen.

Categories