Java Reference
In-Depth Information
Discussion
The UI objects in Java, as in most GUI systems, are not thread-safe (see
Chapter 22
), mean-
ing you are only allowed to update GUI components from within a single thread, the system-
provided UI thread or “event dispatcher thread” (EDT). The first GUI component that gets
created in a given JVM instance starts this GUI
Thread
of control running, and both this
thread and your main thread could be doing things to the GUI at the same time. A Java-lan-
guage “main program” does not run on this thread, thus it should not run UI updates, even
seemingly simple ones such as
setVisible(true)
. In some versions of Java, this restriction
is not enforced and, like jaywalking in a big city, can usually (but not always) be gotten away
with. Apple's Java is particularly prone to enforcing this, yielding the message about
Cocoa
AWT: Running on AppKit thread 0 when not expected
.
There are two classes you can use to run your GUI startup on the event thread, with the same
two static methods in each. In all cases, you pass a
Runnable
into the methods, which will
get run on the correct thread.
EventQueue
and
SwingUtilities
are the classes; the methods
Example 14-2
)
. The former may be called on any thread; the latter may, of course, not be
called on the EDT because it would result in the EDT thread waiting for itself, which never
ends well. The code to start the GUI in a thread-safe way is only a few lines longer than call-
ing it directly from main, but makes for a more reliable application.
Example 14-1. Run on EDT via EventQueue.invokeLater
public
public class
JFrameDemoSafe
{
// We need a main program to instantiate and show.
public
class
JFrameDemoSafe
public static
static
void
void
main
(
String
[]
args
) {
// Create the GUI (variable is final because used by inner class).
final
final
JFrame demo
=
new
new
JFrameDemo
();
// Create a Runnable to set the main visible, and get Swing to invoke.
EventQueue
.
invokeLater
(
new
new
Runnable
() {
public
public
void
void
run
() {
demo
.
setVisible
(
true
true
);
}
});
}
}
Example 14-2. Run on EDT via SwingUtilities.invoke