Swing and Threads

The Java Swing framework has several problems in connection with multi-threaded programs. This page introduces some of them.

In a Swing program there is always one thread executing that is not visible in the user source code: the event-dispatching thread. This thread executes all code in event handlers (listeners), for example in actionPerformed, mouseClicked etc. These event handlers typically update both program state and the GUI. Thus it is essential that all user code that causes GUI updates executes in this thread to avoid race conditions, with different threads concurrently manipulating the GUI. One exception to this rule is the creation of the GUI at program startup, which is often done in the main thread. This is (almost) OK, as long as all the creation work is done before the GUI is realized (made visible on screen).

In the program of Exercise 2, the method addBall in class BallWorld may look overly complicated. A much simpler and seemingly corrrect version would be

public void addBall(Ball b) {
   balls.add(b);
}

However, with this version there is a potential conflict with the single-thread rule of Swing: a ball thread might be created and add itself to the world just when the world is painting itself by iterating of balls, drawing all its elements. This might lead to unpredictable results. But, in fact, in this case the problem will be detected at run-time: the iterator code will note that the data structure it is iterating over is changing in the middle of the iteration and will throw a ConcurrentModificationException. You might want to replace addBalls with the above simpler version and see that this actually happens. Worse, it happens in some executions of the program, which may cause it to be undetected during testing.

To avoid the problem, we must add the ball from the event-dispatching thread. Exactly this is achieved by creating a Runnable object with the desired code in the run method and calling the static method invokeLater from SwingUtilities with this object as argument. Every Swing programmer will sooner or later need to learn this. In recent editions of Sun's Swing tutorial, it is taught sooner rather than later, in fact so soon as to make Swing programming seem inaccessible to an introductory programming course.

Finally: where is the conflict with the simple version of addBall; there is no sign in the program of the event-dispatching thread being used at all? The answer is hidden in the window-refreshing thread (in class Balls), which repeatedly calls win.repaint(); that method call, in turn, queues a call to paintComponent in BallWorld from the event-dispatching thread. (Unfortunately, even this complicated explanation is a simplification of what really happens.)

To learn more about these things, do a Google search on the two (essential) words in the title of this page.

Last modified: Tuesday, 20-Aug-2013 16:01:20 CEST
COMPUTER SCIENCE AND ENGINEERING - Chalmers University of Technology and Göteborg University
SE-412 96 Göteborg, Sweden - Tel: +46 (0)31- 772 1000