Multithreading in Swing

An important compromise was made early in the design of Swing relating to speed, GUI consistency, and thread safety. To provide maximum performance and simplicity in the common case, Swing does not explicitly synchronize access to most Swing component methods. This means that most Swing components are, technically, not thread-safe for multithreaded apps. Now don't panic: it's not as bad as it sounds because there is a plan. All event processing in AWT/Swing is handled by a single system thread using a single system event queue. The queue serves two purposes. First, it eliminates thread-safety issues by making all GUI modifications happen in a single thread. Second, the queue imposes a strict ordering of all activity in Swing. Because painting is handled in Swing using events, all screen updating is also ordered with respect to all event handling. What this means for you is that multithreaded programs need to be careful about how they update Swing components after they are realized (added to a visible container). If you make arbitrary modifications to Swing components from your own threads, you run the risk of malformed rendering on the screen and inconsistent behavior. There are several conditions under which it is always safe to modify a Swing component. First, Swing components can be modified before they are realized. The term realized originates from the days when the component would have created its peer object. It is the point when it is added to a visible container or when it is made visible in the case of a window. Most of our examples in this tutorial set up GUI components in their main( ) method, add them to a JFrame, and then, as their final action, cause the JFrame to be displayed using setVisible( ). This setup style is safe because components are not realized until the container is made visible. Actually, that last sentence is not entirely true. Technically, components can also be realized by the JFrame( ) pack( ) method. However, since no GUI is shown until the container is made visible, it is unlikely that any GUI activity can be mishandled. Second, it's safe to modify Swing components from code that is already running from the system event handler's thread. Because all events are processed by the event queue, the methods of all Swing event listeners are normally invoked by the system event-handling thread. This means that event handler methods and, transitively, any methods called from those methods during the lifetime of that call, can freely modify Swing GUI components because they are already running in the system event-dispatching thread. If you are unsure of whether some bit of code will ever be called outside the normal event thread, you can use the static method SwingUtilities.isEventDispatchThread( ) to test the identity of the current thread. You can then perform your activity using the event-queue mechanism we'll talk about next. Finally, Swing components can be safely modified when the API documentation explicitly says that the method is threadsafe. Many important methods of Swing components are explicitly documented as threadsafe. These include the JComponent repaint( ) and revalidate( ) methods, many methods of Swing text components, and all listener add and remove methods. If you can't meet any of the requirements for thread safety listed previously, you can use a simple API to get the system event queue to perform arbitrary activities for you on the event-handling thread. This is accomplished using the invokeAndWait( ) or invokeLater( ) static methods of the javax.swing.SwingUtilities class:



public static void invokeLater(Runnable doRun)

Use this method to ask Swing to execute the run( ) method of the specified Runnable.



public static void invokeAndWait(Runnable doRun)throwsInterruptedException,InvocationTargetException

This method is just like invokeLater( ) except that it waits until the run( ) method has completed before returning.

You can put whatever activities you want inside a Runnable object and cause the event dispatcher to perform them using these methods. Often you'll use an inner class, for example:

 SwingUtilities.invokeLater( new Runnable( ) {
 public void run( ) {
 MyComponent.setVisible(false);
 }
 } );


You may find that you won't have to use the event dispatcher in simple GUI apps because most activity happens in response to user interface events where it is safe to modify components. However, consider these caveats when you create threads to perform long-running tasks such as loading data or communicating over the network.

Comments