Threads and Swing

This section tells you
how to use the Swing API in a thread-safe way.
If your program is an application (not an applet)
and has the following common pattern,
then you don't need to worry about thread safety:

However, if your program is an applet,
creates threads to perform tasks
that affect the GUI,
or manipulates the already-visible GUI
in response to anything but an AWT event,
then read on!
Four subsections follow; please read at least the first two.

Rule: Once a Swing component has been realized,
all code that might affect or depend on the state of that component
should be executed in the event-dispatching thread.

This rule might sound scary, but for many simple programs, you don't
have to worry about threads. Before we go into detail about how to write
Swing code, let's define two terms: realized and event-dispatching
thread.

Realized means that the component's paint method
has been or might be called. A Swing component that's a top-level window
is realized by having one of these methods invoked on it: setVisible(true),
show, or (this might surprise you) pack. Once
a window is realized, all components that it contains are realized. Another
way to realize a component is to add it to a container that's already realized.
You'll see examples of realizing components later.

The event-dispatching thread is the thread that executes drawing
and event-handling code. For example, the paint and actionPerformed
methods are automatically executed in the event-dispatching thread. Another
way to execute code in the event-dispatching thread is to use the SwingUtilitiesinvokeLater method.

There are a few exceptions to the rule that all code that might affect
a realized Swing component must run in the event-dispatching thread:

A few methods are thread-safe.

In the Swing API documentation,
thread-safe methods are marked with this text:

This method is thread safe, although most Swing methods are not.
Please see Threads and Swing for more information.

An application's GUI can often be constructed and shown in
the main thread.

As long as no components (Swing or otherwise)
have been realized in the current runtime environment,
it's fine to construct and show a GUI
in the main thread
of an application.
To help you see why, here's an analysis of the thread safety of the
thread-safe example.
To refresh your memory, here are the important lines from the example:

The example constructs the GUI in the main thread.
In general, you can construct (but not show)
a GUI in any thread,
as long as you don't make any calls
that refer to or affect already-realized components.

The components in the GUI are realized
by the pack call.

Immediately afterward,
the components in the GUI are shown with the
setVisible
(or show) call.
Technically, the setVisible call
is unsafe because the components have already been realized
by the pack call.
However, because the program
doesn't already have a visible GUI,
it's exceedingly unlikely that a paint call will occur
before setVisible returns.

The main thread executes no GUI code after
the setVisible call.
This means that all GUI work moves
from the main thread to the event-dispatching thread,
and the example is, in practice,
thread-safe.

The following
JComponent methods are safe to call
from any thread:
repaint,
revalidate,
and invalidate.

The repaint and revalidate methods enqueue
requests for the event-dispatching thread to call paint
and validate, respectively. The invalidate
method just marks a component and all of its direct ancestors as requiring
validation.

Listener lists can be modified from any thread.

It's
always safe to call the addListenerTypeListener
and removeListenerTypeListener methods. The add/remove
operations have no effect on an event dispatch that's under way.

Most post-initialization GUI work naturally occurs in the event-dispatching
thread. Once the GUI is visible, most programs are driven by events such
as button actions or mouse clicks, which are always handled in the event-dispatching
thread.

However, some programs need to perform non-event-driven GUI work after
the GUI is visible. Here are some examples:

Applets:

Because every applet is added to an already
visible page, the code that adds components to the applet should be executed
in the event-dispatching thread.
[PENDING: link to JApplet page]

Programs that must perform a lengthy initialization operation
before they can be used:

This kind of program should generally
show some GUI while the initialization is occurring,
and then update or change the GUI.
The initialization should not occur in the event-dispatching
thread;
otherwise, repainting and event dispatch would stop.
However, after initialization the GUI update/change
should occur in the event-dispatching thread,
for thread-safety reasons.

Programs whose GUI must be updated as the result of non-AWT
events:

For example, suppose a server program can get requests
from other programs that might be running on different machines. These
requests can come at any time, and they result in one of the server's methods
being invoked in some possibly unknown thread. How can that method update
the GUI? By executing the GUI update code in the event-dispatching thread.

The SwingUtilities class provides two methods to help you
run code in the event-dispatching thread:

invokeLater:
Requests that some code be executed in the event-dispatching thread. This
method returns immediately, without waiting for the code to execute.

invokeAndWait: Acts like invokeLater,
except that this method waits for the code to execute. As a rule, you should
use invokeLater instead of this method.

Using the invokeLater Method

You can call invokeLater from any thread to request the
event-dispatching thread to run certain code. You must put this code in
the run method of a Runnable object and specify
the Runnable object as the argument to invokeLater.
The invokeLater method returns immediately, without waiting
for the event-dispatching thread to execute the code. Here's an example
of using invokeLater:

Using the invokeAndWait Method

The invokeAndWait method is just like invokeLater,
except that invokeAndWait doesn't return until the event-dispatching
thread has executed the specified code. Whenever possible, you should use
invokeLater instead of invokeAndWait. If you
use invokeAndWait, make sure that the thread that calls invokeAndWait
does not hold any locks that other threads might need while the call is
occurring.

If you can get away with it, avoid using threads. Threads can be difficult
to use, and they make programs harder to debug. In general, they just aren't
necessary for strictly GUI work, such as updating component properties.

However, sometimes threads are necessary. Here are some typical
situations where threads are used:

To perform a time-consuming task without locking up the event-dispatching
thread. Examples include making extensive calculations, doing something
that results in many classes being loaded (initialization, for example),
and blocking for network or disk I/O.

To perform an operation repeatedly, usually with some predetermined
period of time between operations.

Timer: Creates a
thread that executes some code one or more times, with a user-specified
delay between executions. For detailed information about timers,
see How to Use Timers.

Using the SwingWorker Class

The SwingWorker class is implemented
in SwingWorker.java,
which is not in the Swing release. SwingWorker does
all the dirty work of implementing a background thread. Although many programs
don't need background threads, background threads are sometimes useful for
performing time-consuming operations, which can improve the perceived performance
of a program.

To use the SwingWorker class, you first create a subclass
of it. In the subclass, you must implement the construct method
so that it contains the code to perform your lengthy operation. When you
instantiate your SwingWorker subclass, the SwingWorker
creates a thread that calls your construct method. When you
need the object returned by the construct method, you call
the SwingWorker's get method. Here's an example
of using SwingWorker:

When the program's main method creates the SwingWorker
object, the SwingWorker immediately starts a new thread that
instantiates ExpensiveDialogComponent. The main
method also constructs a GUI that consists of a window with a button.

When the user clicks the button, the program
blocks, if necessary, until the ExpensiveDialogComponent has
been created. The program then shows a modal dialog containing the ExpensiveDialogComponent.
You can find the entire program in PasswordDemo.java.
Also, the example program provided in
How to Use Progress Bars runs a long task
in a SwingWorker thread.