Search code examples
javamultithreadingswingevent-dispatch-threadinvokelater

Using SwingUtilities.invokeLater() in main method


I recently saw a MVC java application in which the main method was written as:

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                View view = new View();
                Model model = new Model();
                Controller controller = new Controller(view, model);
                controller.start();
            }
        });
    }

Wouldn't this make all the program (including both the model and the controller, that have nothing to do with Swing at all) run until the code ends in the AWT Event Dispatch Thread instead of the Main thread?

If this last was true, then that would be really bad for the app as it would block the EDT from carrying out the tasks it needs to (dispatching events, for example, as the model could be calculating other tasks). Is it correct?


There is a similar old post (not a duplicate from this one) that can suggest the code mentioned above is good practice, so it confused me even more.


Solution

  • The purpose of the code fragment that you show is to create the Swing UI and the model and to connect them together.

    There is no Swing update (in terms of reacting to user input) since there cannot be any user input before the run() methods ends.

    While you could split these tasks between main thread and EDT (and possibly gain a few milliseconds until the UI is first shown) it would also complicate the design of the application (multithreading is no easy topic) and litter the code base with invokeLater() calls. I would not do it until someone proves it to be necessary.


    IMHO the EDT is the main thread in any GUI application. Every reaction to user input starts in this thread and every update of the UI must be done in this thread.

    Long running tasks should be done in a background thread - which usually means anything that takes more than a few milliseconds.

    What if creating the model takes several seconds?

    In that case I would try to split the model creation into two parts:

    • create the minimal part that is needed so that the UI can be shown. This should be done in the EDT (because the user has to wait for the completion of this part anyway - before the UI is shown he cannot interact with it)
    • do the remaining, long running parts in a background thread.

    What if this cannot be done? (i.e. the UI cannot be displayed until the model is fully initialized)

    In this case the user has to wait for the complete initialization of the model before he can see and use the UI anyway. So it doesn't matter whether this initialization runs on the EDT or the main thread. So use the simpler solution: everything on the EDT.

    But give the user some hint that your application is starting by showing a splash screen