Why do people run Java GUI's on the Event Queu

2019-01-19 00:27发布

问题:

In Java, to create and show a new JFrame, I simply do this:

public static void main(String[] args) {
   new MyCustomFrameClass().setVisible(true);
}

However, I have seen many people doing it like this:

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MyCustomFrameClass().setVisible(true);
       }
    });
}

Why? Are there any advantages?

回答1:

The rules governing what needs to be performed on the EDT (I see "EDT" more often used than "Event Queue") have changed during Java's lifetime. And everytime the "rules" changed, Sun advised doing more and more "GUI related" work on the EDT.

Why do people run Java GUI’s on the EDT?

  • Because the official guidelines advise doing so.

  • Because doing so will help dodge a lot of threading bugs related to the GUI.

Note, and this is not very well known, that the EDT actually does crash once in a while, because Swing itself has a few bugs. Every non-trivial Swing application is using Swing APIs that have, well, bugs and hence once in a while the EDT dies.

You never see it and it isn't a cause of concerns, because when the EDT dies it is automagically restarted.

Basically, do all GUI-related stuff on the EDT and do all lenghty operations outside the EDT (as to not block the EDT).

EDIT you asked for an example as to how to run a lenghty operation outside the EDT. There are several ways to do this. In the simplest case, you simply create and start a new Thread, from the EDT. Here's one example: the listener callback shall be called when the user clicks on a button, we know that this shall happen on the EDT...

    JButton jb = ...
    jb.addActionListener( new ActionListener() {
        public void actionPerformed( final ActionEvent e ) {
          final Thread t = new Thread( new Runnable() {
           public void run() {
             // this shall get executed, after start() has been called, outside the EDT    
             }
           });
           t.start();
        }
    } );

For more complicated examples, you want to read on SwingWorker, etc.



回答2:

This line is modifying a Swing component since your custom frame is a subclass of JFrame:

new MyCustomFrameClass().setVisible(true);

Generally, you should never modify a Swing component unless you are on the Event Dispatch Thread (EDT).

The following code will run whatever is in the Runnable on the EDT.

EventQueue.invokeLater(Runnable);

Now, the setVisible(true) call will be on the EDT as it should.