SwingUtilities.invokeLater() why is it needed?

JavaSwing

Java Problem Overview


Why is it necessary to put GUI update code in SwingUtilities.invokeLater()?

Why cant it be internally taken care of by Swing itself? Why does the caller have to care about how swing handles UI updates?

Java Solutions


Solution 1 - Java

Swing objects are not thread safe. SwingUtilities.invokeLater() allows a task to be executed at some later point in time, as the name suggests; but more importantly, the task will be executed on the AWT event dispatch thread. When using invokeLater, the task is executed asynchronously; there's also invokeAndWait, which won't return until the task has finished executing.

Some information about the decision not to make Swing thread-safe can be found here: Multithreaded toolkits: A failed dream? [Archived]

Solution 2 - Java

Because GUI updates must be done in the event dispatch thread. If you're operating in a different thread, doing the update in invokeLater yanks it out of your thread and into the event thread.

More explanation here: http://www.oracle.com/technetwork/java/painting-140037.html

The smart thing to do with big updates (like repopulating a JTable from the database) on Swing is to get the underlying model, do the updates on the model in your thread, then fire off a notification using invokeLater. That keeps your gui responding to events and redrawing. If the update is going to be very extensive, you can even fire off these notifications with invokeLater at regular intervals while you're updating, like every second or two.

Solution 3 - Java

Swing is single-threaded. Every update to the UI must happen from the so-called EDT – the event-dispather thread which is the main GUI thread Swing (and I think AWT) uses. If you don't do this, then weird things can or will happen (though I like Windows Forms better here which just throws an exception if you do it wrong).

That being said, you don't need to wrap every single UI operation into SwingUtilities.invokeLater() – if the code you're writing is already executed by the EDT this isn't needed. So the ActionListener for a button click doesn't need this. But a listener on an external object, running in some other thread, that updates a JLabel somewhere – there you need it.

Solution 4 - Java

Swing was not written to be a thread safe GUI toolkit so all GUI updates should happen from a single thread to avoid any deadlocks. In Swing this is the Event Dispatcher Thread (EDT).

See Concurrent in Swing from the Java tutorial for more details. It also references this blog entry on why it is hard to write a multithreaded GUI toolkit.

Solution 5 - Java

All the painting of the components should be performed in a single thread, so, they are rendered properly. That way the component will know, what part has already been painted and which part hasn't.

If you invoke a "painting" related method ( paint, update, paintComponent, show, setVisible, pack etc. ) outside the EDT, you'll be trying to paint in two different threads, and that may bring problems.

When you need to use another thread to update the UI, you should invoke it with the invokeLater facility, which in turn will put it in the EDT for you, so you still paint in the same thread.

You don't need to use it, if you're coding in a method that runs in the EDT already ( for instance, actionPerformed or paint or one of those ) Or if you are executing code not UI related ( for instance, processing files in the background etc. )

To better understand all these concepts read:The single thread rule

Solution 6 - Java

SwingUtilities.invokeLater() >Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI.
...

Solution 7 - Java

Repeating others: Swing is not thread safe so one thread must do all the updates to avoid concurrency problems. invokeLater is an utility method to execute something inside the event processing thread.

Why doesn't Swing does it internally: this is my impression... I think because it would be overkill -to check every place where an update is taking place. It would bloat the Swing code, dificult the review and maintainability of the code.

By the other hand it's not that dificult for an application to know if it's not executing inside the GUI thread and call invokeLater. It will be when the own application launched some thread before.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionpure.javaView Question on Stackoverflow
Solution 1 - JavaRichard FearnView Answer on Stackoverflow
Solution 2 - JavaPaul TomblinView Answer on Stackoverflow
Solution 3 - JavaJoeyView Answer on Stackoverflow
Solution 4 - JavaMarkView Answer on Stackoverflow
Solution 5 - JavaOscarRyzView Answer on Stackoverflow
Solution 6 - JavaColin HebertView Answer on Stackoverflow
Solution 7 - JavaheliosView Answer on Stackoverflow