Java: Swing Libraries & Thread Safety Java: Swing Libraries & Thread Safety multithreading multithreading

Java: Swing Libraries & Thread Safety


  1. Never do long running tasks in response to a button, event, etc as these are on the event thread. If you block the event thread, the ENTIRE GUI will be completely unresponsive resulting in REALLY pissed off users. This is why Swing seems slow and crusty.

  2. Use Threads, Executors, and SwingWorker to run tasks NOT ON THE EDT ( event dispatch thread).

  3. Do not update or create widgets outside of the EDT. Just about the only call you can do outside of the EDT is Component.repaint(). Use SwingUtilitis.invokeLater to ensure certain code executes on the EDT.

  4. Use EDT Debug Techniques and a smart look and feel (like Substance, which checks for EDT violation)

If you follow these rules, Swing can make some very attractive and RESPONSIVE GUIs

An example of some REALLY awesome Swing UI work: Palantir Technologies. Note: I DO NOT work for them, just an example of awesome swing. Shame no public demo... Their blog is good too, sparse, but good


This is one of those questions that makes me glad I purchased Robinson & Vorobiev's book on Swing.

Anything that accesses the state of a java.awt.Component should be run inside the EDT, with three exceptions: anything specifically documented as thread-safe, such as repaint(), revalidate(), and invalidate(); any Component in a UI that has not yet been realized; and any Component in an Applet before that Applet's start() has been called.

Methods specially made thread-safe are so uncommon that it's often sufficient to simply remember the ones that are; you can also usually get away with assuming there are no such methods (it's perfectly safe to wrap a repaint call in a SwingWorker, for example).

Realized means that the Component is either a top-level container (like JFrame) on which any of setVisible(true), show(), or pack() has been called, or it has been added to a realized Component. This means it's perfectly fine to build your UI in the main() method, as many tutorial examples do, since they don't call setVisible(true) on the top-level container until every Component has been added to it, fonts and borders configured, etc.

For similar reasons, it's perfectly safe to build your applet UI in its init() method, and then call start() after it's all built.

Wrapping subsequent Component changes in Runnables to send to invokeLater() becomes easy to get right after doing it only a few times. The one thing I find annoying is reading the state of a Component (say, someTextField.getText()) from another thread. Technically, this has to be wrapped in invokeLater(), too; in practice, it can make the code ugly fast, and I often don't bother, or I'm careful to grab that information at initial event handling time (typically the right time to do it in most cases anyway).


It's not just that Swing is not thread-safe (not much is), but it's thread-hostile. If you start doing Swing stuff on a single thread (other than the EDT), then when in cases where Swing switches to the EDT (not documented) there may well be thread-safety issues. Even Swing text which aims to be thread-safe, isn't usefully thread-safe (for instance, to append to a document you first need to find the length, which might change before the insert).

So, do all Swing manipulations on the EDT. Note the EDT is not the thread the main is called on, so start your (simple) Swing applications like this boilerplate:

class MyApp {    public static void main(String[] args) {        java.awt.EventQueue.invokeLater(new Runnable() { public void run() {            runEDT();        }});    }    private static void runEDT() {        assert java.awt.EventQueue.isDispatchThread();        ...