Main Thread vs. UI Thread in Java
Asked Answered
T

3

11

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?

Tomcat answered 23/8, 2011 at 6:13 Comment(2)
yes you have to wraps main methods in all of cases, yes most of JComponents are thread safe, but not valid for their nested and inherits methods, nothing else, sorry yes maybe this one .Degrade
See also this Q&A that examines "Why are GUIs single-threaded?"Medium
M
19

"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. As violations may be obscure, verify correct usage by using one of the approaches mentioned here.

Medium answered 23/8, 2011 at 9:0 Comment(0)
D
2

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.

Dragonnade answered 23/8, 2011 at 6:26 Comment(4)
It's not just a way to execute some code asynchronously. It executes the given Runnable in the Event Dispatcher Thread, and that depending on the situation could make a differenceBogoch
@ Luismahou, thank you. I did not know this difference. What are the benifits of executing the code in event dispatching thread? I only know disadvantages: if task for some reason takes long time it can block other events from dispatching.Dragonnade
In general Swing-related code should be executed in the EDT. Why? Simply because Swing doesn't support multithreading. For example, if you change the text of a JLabel in thread different from the EDT, while the EDT is executing the paint() method of that same JLabel, something unexpected may happen. Regarding the disadvantage, SwingWorker is the official solution, which helps to execute non-UI code outside the EDT.Bogoch
Note: JLabel.setText is not a good example because it runs in the EDT by default (and some others too). But in case of doubt, run in the EDT.Bigotry
F
1

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.

Fumigate answered 23/8, 2011 at 6:22 Comment(3)
Regarding your example - it's pretty close to the 2nd example I gave (from Java's site). So you say it's about the "peace of mind", right?Tomcat
Yes, because at that point (just entering main) what else would be realized on the screen? Nothing, because you haven't done anything yet! Beyond that very very specific case you must take great care to only execute Swing code on the EDT. Personally, I've done Swing programming for years and never ran into trouble creating my UI straight out of main.Fumigate
I play only a few years with Swing, but I never ran into a problem either. I guess that I didn't run to complex UI applications...Tomcat

© 2022 - 2024 — McMap. All rights reserved.