Unlike other graphical program interfaces (hereafter APIs), Swing works on a single thread model. This single thread is responsible for both the GUI (graphical user interface) and the processing of all events received from the user. This means that the developer must pay special attention to the processing of everything that touches the GUI in any way, as well as to how long it will take to process a particular event.
Neglecting this may result in an application that is slower to respond to user actions or fails to work at all. Worse, the application may throw an emergency exception in the event stream, resulting in unpredictable behavior of the entire application.
Single thread
The Swing API is entirely designed to run in a single thread. This means that when that single thread is blocked or slowed down, the entire GUI will run slower or stop responding to user actions altogether. To avoid this, the application should do most of its work in a separate thread and only interact with the event thread when it is handling an event or when there is a need to update (or redraw) the GUI.
Fortunately, most of the Swing API is already designed for this multi-threaded approach, but that’s if the application conforms to the design fundamentals of that API. The pitfalls are not difficult to avoid. The difficulties arise when dealing with events.
Unsafe operations in threads
Another common situation is trying to update a GUI from outside of an event stream. This situation is the exact opposite of the one we discussed above. Listing 2 shows an example where we have more than one thread in an application and a third-party thread tries to update the GUI. While this code may look perfectly safe (and in fact, in a simple situation like this, it probably is safe) – it’s a recipe for getting a lot of no-one’s problems.
Because Swing is designed on a single-threaded model, its API is not synchronized and therefore not protected from attempts by other threads to modify its data. This means that we can get a dangerous collision in the GUI if it tries to update items from any other thread rather than directly from the event thread. Such actions can lead to data corruption, exception throwing, and a host of other dangerous problems that are damn hard to detect and debug. To avoid this problem, you should always update the GUI from the event stream.
Event Stream
If we can’t work in an event stream, how will our application do anything at all? It’s simple. Whenever we’re dealing with a situation where we know an event might take a long time to process, bring it into the worker thread.
Listing 3 is a rewrite of Listing 1, where instead of blocking the event thread until the wait method completes, we create an anonymous inner class that extends java.lang.Thread that will call the wait method for us. In this version of the code, the event will no longer wait for the wait method to complete, but will simply return control to the rest of the application (passing the event to other listeners) after the new thread has initialized and started. As a result, we have a fast response to events and not a slow GUI.