Previous | Next | Trail Map | Creating a GUI with JFC/Swing | Using Other Swing Features

How to Use Threads

[PENDING: introduce. This page needs a bit more glue and perhaps a reorg.] This page gives you some examples of using the thread-related Swing API. For conceptual information, see Threads and Swing(in the Creating a User Interface trail). For more examples, see the BINGO example, especially the following classes: CardWindow, ControlPane, Player, and OverallStatusPane.

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:

Runnable doWorkRunnable = new Runnable() {
    public void run() { doWork(); }
};
SwingUtilities.invokeLater(doWorkRunnable);

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.

Here's an example of using invokeAndWait:

void showHelloThereDialog() throws Exception {
    Runnable showModalDialog = new Runnable() {
        public void run() {
            JOptionPane.showMessageDialog(myMainFrame,
	                                  "Hello There");
        }
    };
    SwingUtilities.invokeAndWait(showModalDialog);
}

Similarly, a thread that needs access to GUI state, such as the contents of a pair of text fields, might have the following code:

void printTextField() throws Exception {
    final String[] myStrings = new String[2];

    Runnable getTextFieldText = new Runnable() {
        public void run() {
            myStrings[0] = textField0.getText();
            myStrings[1] = textField1.getText();
        }
    };
    SwingUtilities.invokeAndWait(getTextFieldText);

    System.out.println(myStrings[0] + " " + myStrings[1]);
}

How to Create Threads

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:

You can use two classes to help you implement threads:

Using the SwingWorker Class


Note: The tutorial's implementation of the SwingWorker class was updated in the January 1999 release of the tutorial; the class has been enhanced to allow programs to safely interrupt the thread. If you are using SwingWorker in any of your programs, make sure you are using this version!
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:

...//in the main method:
    final SwingWorker worker = new SwingWorker() {
        public Object construct() {
            return new ExpensiveDialogComponent();
        }
    };

...//in an action event handler:
    JOptionPane.showMessageDialog
        (f, worker.get());

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 Monitor Progress runs a long task in a SwingWorker thread.


This section is based on an article in The Swing Connection. For more information about Swing thread issues, see the article: Threads and Swing and Using a SwingWorker Thread.


Previous | Next | Trail Map | Creating a GUI with JFC/Swing | Using Other Swing Features