Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Programming Java threads in the real world, Part 5

Has Sun abandoned 'run anywhere'? Plus: Threads and Swing, timers, and getting around stop(), suspend(), and resume() deprecation

  • Print
  • Feedback

Page 3 of 5

The thread-safety issue is an important one. Swing's threading support is described in depth in a Tech note on the Sun Web site, but to summarize: Swing, like AWT before it, uses a single thread to field all user interface (UI) events that come in from the operating system. This thread dequeues OS events from some sort of event queue, figures out what the OS is trying to tell it, and then notifies any listeners interested in the event. For example, the event thread could dequeue a WM_MOUSEMOVE message from the Windows message queue, and then send out mouseMoved() messages to all the interested MouseMotionListener objects.

These event handler methods (such as mouseMoved()) actually run on the thread that's dequeueing the OS-level events. This single-threaded approach is a big issue, because the UI is effectively locked while the event handler messages are executing. That is, no OS-level messages (such as button presses) are serviced while listener notifications are in progress. To keep your UI responsive to user input, these event handler functions should be very short and very fast. They must spawn off threads to do time-consuming operations.

To make matters more interesting, none of Swing class's methods are thread safe -- they are simply not designed to handle the case of two threads accessing them simultaneously. The performance hit required to make Swing thread-safe (not to mention the extra complexity) is just unacceptable. The lack of thread safety means that once you start up the Swing event handler thread (by calling setVisible(), pack(), or any other method that makes a window visible), you cannot safely call a Swing method from anywhere but Swing's own event handler thread. (Note that you can safely manipulate Swing objects before the event handling thread starts -- before you call setVisible() or pack(), for example.)

The lack of thread safety is often not an issue because Swing methods are, more often than not, called from Swing's own event handler thread -- remember, all the listener methods run on that thread. For example, a listener's event handler like mouseMoved() might pass a repaint() message to some Component. This operation is safe because mouseMoved() is running on Swing's own thread.

The invokeLater() and invokeAndWait() methods
There are often cases where some thread of your own devising needs to communicate with Swing, however. For example, the main thread of an application could fire up a window, do some stuff, then want to modify the window. Since you obviously need to pass messages to Swing at times other than initialization time, a mechanism has been provided to ask the Swing event-handling thread to execute a block of code for you. You need to encapsulate your code into a Runnable object, and then pass that object to Swing by calling SwingUtilities.invokeLater() or SwingUtilities.invokeAndWait(). For example, a thread could force a window to redraw itself like this:

    Component some_window = ... ;
    Swingutilities.invokeLater( new Runnable()
                               {   public void run()
                                    {   some_window.repaint();
                                    }
                                }
                              );


The asynchronous invokeLater() message just puts the Runnable object onto the event queue and then returns. The object's run() method is executed when Swing gets around to it. The invokeAndWait() method blocks until the run() function has been executed. Since the associated run() methods run on the Swing event handler thread, synchronously with other Swing methods, the thread safety of the individual Swing methods is irrelevant.

  • Print
  • Feedback

Resources
  • All the real code discussed in this article (the stuff in the com.holub.asynch package) is available in the "Goodies" section on my Web site, http://www.holub.com. The version on the Web site should be considered the definitive version -- at least it corrects any bugs I know about.
  • An article describing Swing's support for threads is at http://java.sun.com/products/jfc/tsc/archive/tech_topics_arch/threads/threads.html
  • You can find documentation for the Swing Timer class in the JDK docs and at http://java.sun.com/products/jdk/1.2/docs/api/javax/swing/Timer.html
  • UML (the Unified Modeling Language) amalgamates the notations of Grady Booch, James Rumbaugh, and Ivar Jacobson. The following three references are recommended:
  • Martin Fowler and Kendall Scott's UML DistilledApplying the the Object Modeling Language (ReadingAddison Wesley, 1997 [ISBN0-201-32563-2]) is a good, quick introduction to UML for those who already know an object-oriented notationhttp://cseng.awl.com/bookdetail.qry?ISBN=0-201-32563-2&ptype=0
  • A more in-depth introduction to UML is Grady Booch, James Rumbaugh, Ivar Jacobson's The Unified Modeling Language User Guide (ReadingAddison Wesley, 1999 [ISBN0-201-57168-4])http://cseng.aw.com/bookdetail.qry?ISBN=0-201-57168-4&ptype=0