Previous | Next | Trail Map | Creating a GUI with JFC/Swing | Swing Features and Concepts

Threads and Swing

If your program creates and refers to its GUI the right way, you might not need to worry about threads. For example, if your program is an applet, it's safe to construct its GUI in the init method. And if your program is an application with the following common pattern, you're also safe:
//Thread-safe example
public class MyApplication {
    public static void main(String[] args) {
	JFrame f = new JFrame(...);
        ...//Add components to the frame here...
	f.pack();
	f.setVisible(true);
	//Don't do any more GUI work here.
    }

    ...
    //All manipulation of the GUI -- setText, getText, etc. --
    //is performed in event handlers such as actionPerformed().
    ...
}
However, if your program creates threads to perform tasks that affect the GUI, or if it manipulates the already-visible GUI in response to anything but a standard event, then read on!

The Single-Thread Rule
Swing components can be accessed by only one thread at a time, generally, the event-dispatching thread.
Exceptions to the Rule
A few operations are guaranteed to be thread safe.
How to Execute Code in the Event-Dispatching Thread
If you need access to the UI from outside event-handling or painting code, you can use the SwingUtilities invokeLater or invokeAndWait method.

The Single-Thread Rule

The single-thread rule is as follows:


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 the term realized.

Realized means that the component has never been painted on-screen, or that it is ready to be painted. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true), show, or pack. Once a window is realized, all the 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.


Note: The show method does the same thing as setVisible(true).

Exceptions to the Rule

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:
public static void main(String[] args) {
    JFrame f = new JFrame(...);
    ...//Add components to the frame here...
    f.pack();
    f.setVisible(true);
    //Don't do any more GUI work here.
}
  1. 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.
  2. The components in the GUI are realized by the pack call.
  3. 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 request will occur before setVisible returns.
  4. 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.

An applet's GUI can be constructed and shown in the init method.
Existing browsers don't paint an applet until after its init and start methods have been called. Thus, constructing the GUI in the applet's init method is safe, as long as you never call show() or setVisible(true) on the actual applet object.

Two JComponent(in the API reference documentation) methods are safe to call from any thread: repaint and revalidate.
These methods queue requests to be executed on the event-dispatching thread.

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.

How to Execute Code in the Event-Dispatching Thread

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 two examples:

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 nonstandard 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(in the API reference documentation) 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 rather than this method.

For information on using invokeLater and invokeAndWait, and for other tips on writing multithreaded programs, see How to Use Threads(in the Creating a User Interface trail).


Previous | Next | Trail Map | Creating a GUI with JFC/Swing | Swing Features and Concepts