You are on page 1of 9

Threads and Swing

SDN Home > Products & Technologies Account Sun Java Solaris Communities My SDN > Java Technology > J2SE > Desktop Java > JFC > News & Updates > The Swing Connection > Reference > Technical Articles and Tips >






Training » search tips

Submit Query Search

Threads and Swing
Print-friendly Version


Threads and Swing

This article about multithreading in Swing was archived in April 1998. A month later, we published another article, "Using a Swing Worker Thread", expanding on the subject. For a better understanding of how multithreading works in Swing, we recommend that you read both articles.
Note: In September 2000 we changed this article and its example to use an updated version of SwingWorker that fixes a subtle threading bug.

By Hans Muller and Kathy Walrath

The Swing API was designed to be powerful, flexible, and easy to use. In particular, we wanted to make it easy for programmers to build new Swing components, whether from scratch or by extending components that we provide. For this reason, we do not require Swing components to support access from multiple threads. Instead, we make it easy to send requests to a component so that the requests run on a single thread. This article gives you information about threads and Swing components. The purpose is not only to help you use the Swing API in a thread-safe way, but also to explain why we took the thread approach we did. Here are the sections of this article:

The single-thread rule: Swing components can be accessed by only one thread at a time. Generally, this thread is the event-dispatching thread. Exceptions to the rule: A few operations are guaranteed to be thread-safe. Event dispatching: If you need access to the UI from outside event-handling or drawing code, then you can use the SwingUtilities invokeLater()or invokeAndWait () method. Creating threads: If you need to create a thread -- for example, to handle a job that's computationally expensive or I/O bound -- you can use a thread utility class such as SwingWorker or Timer. Why did we implement Swing this way?: This article ends with some background information about Swing's thread safety. (1 of 9) [8/18/2010 12:49:15] call is unsafe and should be executed in the eventdispatching thread. in practice. } } All the code shown above runs on the "main" thread. The event-dispatching thread is the thread that executes drawing and event-handling code. show(). all code that might affect or depend on the state of that component should be executed in the event-dispatching thread. // Add components to // the frame let's define two terms: realized and event-dispatching returns.. 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. f..pack().show() call. but for many simple programs. For example. This rule might sound scary.pack() call realizes the components under the JFrame. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true). the f.. This means that. However. technically. you don't have to worry about threads. The f. f. Because there's no GUI code after the threadsafe. thread-safe methods are marked with this text: This method is thread safe. You'll see examples of realizing components later. all components that it contains are realized. although most Swing methods are not.html (2 of 9) [8/18/2010 12:49:15] . Realized means that the component's paint() method has been or might be called. or (this might surprise you) pack(). as long as the program doesn't already have a visible GUI. Another way to execute code in the eventdispatching thread is to use the SwingUtilities invokeLater() method. Another way to realize a component is to add it to a container that's already realized.sun. the paint() and actionPerformed() methods are automatically executed in the event-dispatching thread. and the preceding code is. it's exceedingly unlikely that the JFrame or its contents will receive a paint() call before f. all GUI work moves from the main thread to the event-dispatching thread. as long as no components (Swing or otherwise) have been realized: public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame("Labels"). Before we go into detail about how to write Swing code. Once a window is realized..Threads and Swing Here's the rule: Once a Swing component has been realized. ● An application's GUI can often be constructed and shown in the main thread: The following typical code is safe. // Don't do any more GUI work here.

NOTE: The important difference between revalidate() and the older validate() method is that revalidate() queues requests that might be coalesced into a single validate() call. after initialization the GUI update/change should occur in the event-dispatching thread. The repaint() and revalidate() methods queue requests for the event-dispatching thread to call paint() and validate(). you should start a thread that performs the time-consuming task. As for any applet. ● http://java. and they result in one of the server's methods being invoked in some possibly unknown thread. This is similar to the way that repaint() queues paint requests that might be coalesced. How can that method update the GUI? By executing the GUI update code in the event-dispatching thread. These requests can come at any time. repainting and event dispatch would stop.sun. most programs are driven by events such as button actions or mouse clicks.html (3 of 9) [8/18/2010 12:49:15] . revalidate(). instead.Threads and Swing ● An applet's GUI can be constructed and shown in the init() method: Existing browsers don't draw an applet until after its init() and start() methods have been called. and then update or change the GUI. and components should be added to the JApplet content pane. The invalidate() method just marks a component and all of its direct ancestors as requiring validation. The add/remove operations have no effect on an event dispatch that's under way. suppose a server program can get requests from other programs that might be running on different machines. However. rather than directly to the JApplet. Here are some 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. you should never perform time-consuming initialization in the init() or start() method. ● The following JComponent methods are safe to call from any thread: repaint (). The initialization should not occur in the event-dispatching thread. Once the GUI is visible. for thread-safety reasons. applets that use Swing components must be implemented as subclasses of JApplet. otherwise. some programs need to perform non-event-driven GUI work after the GUI is visible. as long as you never call show() or setVisible(true) on the actual applet object. respectively. constructing the GUI in the applet's init() method is safe. ● Listener lists can be modified from any thread: It's always safe to call the addListenerTypeListener() and removeListenerTypeListener() methods. Most post-initialization GUI work naturally occurs in the event-dispatching thread. which are always handled in the event-dispatching thread. By the way. and invalidate(). However. Programs whose GUI must be updated as the result of non-AWT events: For example.

Whenever possible. except that invokeAndWait() doesn't return until the event-dispatching thread has executed the specified code. } }.html (4 of 9) [8/18/2010 12:49:15] . Using the invokeLater() Method You can call invokeLater() from any thread to request the event-dispatching thread to run certain code. As a rule. without waiting for the code to execute. ● invokeAndWait(): Acts like invokeLater().sun. This method returns immediately. Player. make sure that the thread that calls invokeAndWait() does not hold any locks that other threads might need while the call is occurring. except that this method waits for the code to execute.invokeLater(doWorkRunnable). and OverallStatusPane. You must put this code in the run() method of a Runnable object and specify the Runnable object as the argument to invokeLater(). Here's an example of using invokeAndWait(): void showHelloThereDialog() throws Exception { Runnable showModalDialog = new Runnable() { public void run() { JOptionPane. Also see the BINGO example in The Java especially the following classes: CardWindow.showMessageDialog( myMainFrame.Threads and Swing The SwingUtilities class provides two methods to help you run code in the eventdispatching thread: ● invokeLater(): Requests that some code be executed in the event-dispatching thread. you should use invokeLater() instead of invokeAndWait(). you should use invokeLater() instead of this method. SwingUtilities. If you use invokeAndWait(). The invokeLater method returns immediately. This page gives you some examples of using this API. "Hello There"). ControlPane. } }. 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(). http://java. Using the invokeAndWait() Method The invokeAndWait() method is just like invokeLater().

Threads and Swing SwingUtilities. myStrings[1] = textField1. doing something that results in many classes being loaded (initialization. In general. such as updating component properties.getText(). a thread that needs access to GUI state. Here are some typical situations where threads are used: ● To perform a time-consuming task without locking up the event-dispatching thread.getText().sun. Threads can be difficult to use.out. However. } If you can get away with it. avoid using threads. might have the following code: void printTextField() throws Exception { final String[] myStrings = new String[2].invokeAndWait (showModalDialog). sometimes threads are necessary.invokeAndWait (getTextFieldText).com/products/jfc/tsc/articles/threads/threads1. Runnable getTextFieldText = new Runnable() { public void run() { myStrings[0] = textField0.html (5 of 9) [8/18/2010 12:49:15] . and they make programs harder to debug. they just aren't necessary for strictly GUI work. To wait for messages from clients. ● ● You can use two classes to help you implement threads: ● SwingWorker: Creates a background thread to execute time-consuming operations.println(myStrings[0] + " " + myStrings[1]). Timer: Creates a thread that executes some code one or more times. Examples include making extensive calculations. with a user- ● specified delay between executions. usually with some predetermined period of time between operations. } }. To perform an operation repeatedly. System. such as the contents of a pair of text fields. and blocking for network or disk I/O. for example). http://java. } Similarly. SwingUtilities.

Threads and Swing Using the SwingWorker Class The SwingWorker class is implemented in The main() method also constructs a GUI that consists of a window with a button. you specify how often the timer should perform the operation. you first create a subclass of it.get()). background threads are sometimes useful for performing time-consuming operations. the SwingWorker creates a thread but does not start it. When the user clicks the button. The program then shows a modal dialog containing the ExpensiveDialogComponent. You can find the entire program in MyApplication.html (6 of 9) [8/18/2010 12:49:15] . In the subclass. . Here's an example of using SwingWorker: .showMessageDialog (f. which is not included in any of our releases. To use the SwingWorker class. You invoke start() on your SwingWorker object to start the thread. worker.start(). When you instantiate your SwingWorker the program blocks. When you need the object returned by the construct() method. and you specify which object is the listener for the timer's action events. if necessary. Although many programs don't need background threads. which then calls your construct() method. } }. worker.//in an action event handler: JOptionPane. which can improve the perceived performance of a program. the action listener's actionPerformed() method is invoked one or more times to perform its operation. http://java. the SwingWorker starts a new thread that instantiates ExpensiveDialogComponent. SwingWorker does all the dirty work of implementing a background thread. Using the Timer Class The Timer class works with an ActionListener to perform an operation one or more times. until the ExpensiveDialogComponent has been created. you must implement the construct() method so that it contains the code to perform your lengthy operation.. When you create a timer. Once you start the the main method: final SwingWorker worker = new SwingWorker() { public Object construct() { return new expensiveDialogComponent(). so you must download it separately. When the program's main() method invokes the start() method.. you call the SwingWorker's get() method.

. this).) { . public AnimatorApplicationTimer(. frameNumber++. // Set up a timer that calls this // object's action handler..Threads and Swing The actionPerformed() method defined in the Timer's action listener is invoked in the event-dispatching thread.//are declared: Timer timer.. } public void actionPerformed (ActionEvent e) { //Advance the animation frame... That means that you never have to use the invokeLater() method in it. repaint().. } public void startAnimation() { if (frozen) { // Do nothing. timer.setInitialDelay(0). } There are several advantages in executing all of the user interface code in a single thread: http://java.. timer = new Timer(delay. //Display it.sun..setCoalesce(true). The user has // requested that we stop // changing the image.html (7 of 9) [8/18/2010 12:49:15] . timer. timer.. .//where instance variables ..stop().. Here's an example of using a Timer to implement an animation loop: public class AnimatorApplicationTimer extends JFrame implements ActionListener { . } .start().. } else { //Start (or restart) animating! } } public void stopAnimation() { //Stop the animating thread.

testing. All applications bear the cost of this. and where each program must work under both preemptive or non-preemptive scheduling. the toolkit must regrab its locks and restore its state. we urge you to think twice about using threads in cases where they are not absolutely necessary. any public or protected method in a public class). Whenever the toolkit calls a method that might be implemented in client code (for example. and maintenance vastly more difficult and sometimes impossible. or actual practices of most programmers. and paint requests. of the problem of supporting multithreaded access in a toolkit: It is our basic belief that extreme caution is warranted when designing and building multi-threaded applications. When control returns from the method. such as SubArctic and IFC. Any resulting features and timing of release of such features as determined by Oracle's review http://java. Neither the training. This section describes this mechanism and how to use it to safely manipulate the interactor tree from an independent thread. Events are dispatched in a predictable order: The runnable objects enqueued by invokeLater() are dispatched from the same event queue as mouse and keyboard events. Less overhead: Toolkits that attempt to carefully lock critical sections can spend a substantial amount of time and space managing locks. For example. experience. even though most applications do not require concurrent access to the GUI. In many cases they appear to greatly simplify programming by allowing design in terms of simple autonomous entities focused on a single task. However. However.html (8 of 9) [8/18/2010 12:49:15] . ● ● The thread-safe mechanism they're referring to is very similar to the invokeLater() and invokeAndWait() methods provided by the SwingUtilities class. in which all components must fully support multithreaded access. have designs similar to Swing's. particularly for developers who are not expert at threads programming. timer This is particularly true in Java where one program can run on many different types of machines and OS platforms. Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. can be difficult to extend. particularly those which have a GUI component. written by the authors of the SubArctic Java Toolkit. As a result of these inherent difficulties. This makes comprehensive testing difficult or impossible. Many of the toolkits developed more recently. Here's a description. In fact in some cases they do simplify design and coding. nor the tools we have to help us. in almost all cases they also make debugging. component changes are interleaved with event processing at the whim of the thread scheduler.Threads and Swing ● Component developers do not have to have an in-depth understanding of threads programming: Toolkits like ViewPoint and Trestle. Use of threads can be very deceptive. the toolkit must save its state and release all locks so that the client code can grab locks if necessary. in some cases threads are necessary (or are imposed by other software packages) and so subArctic provides a thread-safe access mechanism.sun. In toolkits where components support multithreaded access. thorough testing (which is always difficult) becomes nearly impossible when bugs are timing dependent. are designed to cope with the non-determinism.

It is intended for information purposes only.Threads and Swing of roadmaps. does not represent a commitment to deliver any material. Oracle Corporation and/or its affiliates http://java.html (9 of 9) [8/18/2010 12:49:15] . and may not be incorporated into any contract. About Sun | About This Site | Newsletters | Contact Us | Employment | How to Buy | Licensing | Terms of Use | Privacy | Trademarks A Sun Developer Network Site Unless otherwise licensed. Sun Developer RSS Feeds © 2010. or functionality. and should not be relied upon in making purchasing decisions. are at the sole discretion of Oracle. All product roadmap information. samples) is provided under this License. code in all technical manuals herein (including FAQs. whether communicated by Sun Microsystems or by Oracle. code.