Main Thread vs. UI Thread in Java

2019-01-02 18:51发布

问题:

In many Swing snippets given here as answers, there is a call to SwingUtilities#invokeLater from the main method:

public class MyOneClassUiApp {

    private constructUi() {
        // Some Ui related Code
    }

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

But according to the Threads and Swing article, it is safe to construct UI from main thread:

A few methods are thread-safe: In the Swing API documentation, thread-safe methods are marked with this text:

This method is thread safe, although most Swing methods are not.

An application's GUI can often be constructed and shown in the main thread: The following typical code is safe, as long as no components (Swing or otherwise) have been realized:

public class MyApplication {
public static void main(String[] args) {
   JFrame f = new JFrame("Labels");
   // Add components to 
   // the frame here... 
   f.pack(); 
   f.show(); 
   // Don't do any more GUI work here... 
   } 
}

So, is there a real (thread safety) reason to construct the UI in main through SwingUtilities#invokeLater, or this is just a habit, to remember do it in other cases?

回答1:

"The Swing single-thread rule: Swing components and models should be created, modified, and queried only from the event-dispatching thread."—Java Concurrency in Practice, also discussed here and here. If you don't follow this rule, then you can't reliably construct, modify or query any component or model that may have assumed that you did follow the rule. A program may appear to work correctly, only to fail mysteriously in a different environment.



回答2:

It's safe to create your Swing UI in the main method because how would other components be displayed before you set up your UI? As long as you haven't thrown some stuff on the screen already you'll be fine. In other words, this would be bad:

public class MyApplication
{ 
  public static void main(String[] args)
  { 
    JFrame f = new JFrame("Labels"); 
    // Add components to  
    // the frame here...  
    f.pack();  
    f.show();  

    // now make another frame:
    JFrame f2 = new JFrame("Labels2"); 
    // Add components to the 2nd frame here...  
    f2.pack();  
    f2.show();  
  }  
}

If you did the above you'd have JFrame f up and running then you'd be adding Swing UI components off the Event Dispatch Thread (EDT). invokeLater runs the code on the EDT - it won't hurt to use it if you want extra peace of mind.



回答3:

I think that using SwingUtiltities.invokeLater() is just an easier way to execute some code asynchronously. Sometimes it is required for certain application: for example you can create 2 separate windows simultaneously. Nothing more.



标签: