Skip to main content

Starting off on the right thread

Posted by joconner on January 11, 2007 at 7:27 PM PST

A new year, new beginnings. Times like this always make me resolve impossible things. Fortunately, there's one thing I can follow through with. I can certainly start off on the right foot, and in this particular resolution, that means starting off on the right thread too.

While working on a new article for Sun's Java Developer site, I realized that I had been making a mistake over and over again. I've been starting app UIs from the wrong thread. In my situation, I haven't noticed anything horribly wrong, but I suspect that problems are possible...strange synchronization problems that are hard to duplicate reliably.

If you're developing Swing applications, you have an important rule to remember. With very few exceptions, you can interact with GUI components and their models only from the Swing event dispatch thread. However, I see apps start up like this all the time:

public class MyApplication extends JFrame {
  ...
  public static void main(String[] args) {
    JFrame app = new MyApplication();
    app.setVisible(true);
  }
  ...
}

The problem here is that the app starts and interacts with the UI from an initial thread, not from the UI event dispatch thread. That setVisible call seems innocent enough, and I know this happens all the time, but really, the code should look more like this:

public static void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      JFrame app = new MyApplication();
      app.setVisible(true);
    }
   });
}

The problem with this example is that it's trivial. From the point of construction to the setVisible call, nothing significant is happening. In more complex construction sequences, there's potential for drawing errors, mismatches between model and views, etc. I suppose any number of things could go wrong. One problem is that most of the time, nothing goes wrong...not in something this simple. That means that people don't see a problem, don't suspect anything, and certainly don't feel the need to fix this.

However, the simple fact of the matter is that all Swing interactions should occur on the EDT...not doing so has been declared unsafe. That usually means that you must use the invokeLater method from non-EDT threads.

Using SwingUtilities, it's easy to create and start your app's UI on the event dispatch thread. Seems so simple, and it is. I might even be able to keep this resolution.

Related Topics >>