Jump to content





Recent Status Updates

  • Photo
      16 Apr
    Kadence

    If you're reading this, you're on my profile and I know you're on my profile because I'm probably viewing yours.

    Show comments (6)
  • Photo
      10 Apr
    Poe

    Finally (and hopefully) i'm getting a team together that knows a little of this and a little of that; and maybe all my open source projects that are half written can begin to be released. :)

View All Updates
Photo
- - - - -

Swing Thread Safety - How to properly modify components.


  • Please log in to reply
No replies to this topic

#1 farrell2k

farrell2k

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 117 posts

Posted 18 June 2010 - 09:08 PM

Swing is not thread safe, so to avoid the possibility of deadlocks, all component realization and modification should be done in the event dispatch Thread (EDT) by invoking SwingUtilities.invokeLater(). It is likely, however, that your applications will work just fine 99% of the time without this. invokeLater adds your action to the EDT.

Example:

Creating a JFrame

package gooey;

import javax.swing.*;

public class Gooey {
    private JFrame frame;

    public Gooey() {
        initComponents();
    }

    private void initComponents() {
        frame = new JFrame("Thread Safety");
        frame.setSize(200,200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[]args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Gooey();
            }
        });
    }
}

This ensures that the EDT is the only thread realizing components. Can you imagine what would happen if new Gooey() was called at the same time from your main thread as well as the event dispatch Thread? A dealock.

The same goes for updating components under different threads. Lets say that you have a while loop in a main game that updates a jLabel via a seperate thread every couple of seconds.

while(!gameOver) {
    label.setText("Game is not over, yet!");
}

Now, if your while loop called on label.setText() at the same time the EDT was repainting that component, a deadlock would occur and your app would freeze. The way to fix this is to do your component updates via the EDT.

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        label.setText("Game not over, yet!");
    }
});
You do NOT have to uset Swingutilities.invokeLater while modifying a component via a gui event such as in an ActionEvent due to a button click, as all ActionEvents happen in the EDT already. Anything in actionPerformed, or any other Listener interface method is executed in the EDT and does not need SwingUtilities.invokeLater() It is also safe to call repaint() anywhere, as all repaint requests occur in the EDT.

Again, you may never use SwingUtilities, and may never have a problem, but you should use it whenever you're updating a component in a situation like the above.
  • 0