A couple of my readers ask questions, what does it mean by Swing is not thread-safe and How does it affect coding in Swing GUI application? This post is an effort to help those readers and several other programmers to understand Swing and thread safety in a bit more detailed way. To keep it simple, let's revise what does it mean by being thread-safe? We say an object is thread-safe if we can call its a method, which can change its states, from multiple threads at the same time. To give you an example, java.lang.String is a thread-safe class, which means you can call any method e.g. substring(), toUpperCase() or toLowerCase() from multiple threads.
By the way, String is a thread-safe because it's immutable. Let's come back to Swing now, The Core part of Swing is made up of different GUI component e.g. JLable, JPanel, JCombobox, etc. All these components are not thread-safe, which means you can not call methods of these components like the JLable.setText("new title") from any thread, other than Event Dispatcher Thread(EDT).
In one word, Since Swing is not thread-safe, you can not update Swing components from any random thread, they are always updated using Event Dispatcher thread. This is, in fact, one of the most popular Java Swing Interview Question, with lot's of interesting follow-up e.g.
If Swing is not thread-safe than how do you update components from other threads? and which methods of Swing API are thread-safe? etc. We will see the answer to this question in the next section.
By the way, String is a thread-safe because it's immutable. Let's come back to Swing now, The Core part of Swing is made up of different GUI component e.g. JLable, JPanel, JCombobox, etc. All these components are not thread-safe, which means you can not call methods of these components like the JLable.setText("new title") from any thread, other than Event Dispatcher Thread(EDT).
In one word, Since Swing is not thread-safe, you can not update Swing components from any random thread, they are always updated using Event Dispatcher thread. This is, in fact, one of the most popular Java Swing Interview Question, with lot's of interesting follow-up e.g.
If Swing is not thread-safe than how do you update components from other threads? and which methods of Swing API are thread-safe? etc. We will see the answer to this question in the next section.
How to update Swing Component from a different thread
Since Swing is not thread-safe by design, it's designer did provide couple of utility methods in SwingUtilities class to update any Swing component from a thread other thread Event Dispatcher Thread. You can use invokeAndWait() and invokeLater() to update a Swing component from any arbitrary thread.
As the name suggests, invokeAndWait() is synchronous, blocking method and blocks until GUI is updated, while invokeLater() is an asynchronous call and doesn't wait for GUI to be updated. By the way, both of these methods make sure that Swing GUI components are updated in EDT thread only. Both of these methods takes a Runnable object, which contains code to update GUI, as shown below :
As the name suggests, invokeAndWait() is synchronous, blocking method and blocks until GUI is updated, while invokeLater() is an asynchronous call and doesn't wait for GUI to be updated. By the way, both of these methods make sure that Swing GUI components are updated in EDT thread only. Both of these methods takes a Runnable object, which contains code to update GUI, as shown below :
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JLable.setText("Update Title");
}
}
to learn more about both of these methods and How to use them, See when to use InvokeAndWait and InvokeLater in Java.
A couple of times, the Interviewer also asks about, how do you find, if a particular thread is Event Dispatcher thread or not? Well, if you are familiar with Swing API, they you may know that SwingUtilities provides isEventDispatchThread() method, which can be used to find out if the current thread is Event Dispatcher thread or not.
Another follow-up question is Why Swing is not thread-safe in Java? Well, this is on similar lines like why multiple inheritance is not supported in Java or Why Java doesn’t support operator overloading.
It's the decision taken by there designer, at that time. Since making an API thread-safe takes a lot of work, and it's often based upon the benefit you get. Since GUI screens are mostly updated in the response of user action e.g. when users click a button, and since events are handled in the same Event dispatcher thread, it's easy to update GUI on that thread. It's very rare when an update request for GUI comes from a different thread e.g. maybe once a network request is complete or a file is loaded.
In such cases, you can use either invokeAndWait(), invokeLater(), or preferably SwingWorker class, which is designed to run these lengthy time-consuming tasks in a separate thread and the same time managing inter-thread communication between a worker thread and Event dispatcher thread.
Since the EDT thread is most important in Swing and is responsible for listening event and updating GUI, you must not do any time-consuming task on it, otherwise, you risk your application becoming unresponsive or frozen. Another key thing to note, while using multi-threading in Swing development is that, not only GUI components but there model e.g. TableModel for JTable, must be updated in Event Dispatcher thread. One of the crucial difference between AWT and Swing is that AWT components are thread-safe
Another follow-up question is Why Swing is not thread-safe in Java? Well, this is on similar lines like why multiple inheritance is not supported in Java or Why Java doesn’t support operator overloading.
It's the decision taken by there designer, at that time. Since making an API thread-safe takes a lot of work, and it's often based upon the benefit you get. Since GUI screens are mostly updated in the response of user action e.g. when users click a button, and since events are handled in the same Event dispatcher thread, it's easy to update GUI on that thread. It's very rare when an update request for GUI comes from a different thread e.g. maybe once a network request is complete or a file is loaded.
In such cases, you can use either invokeAndWait(), invokeLater(), or preferably SwingWorker class, which is designed to run these lengthy time-consuming tasks in a separate thread and the same time managing inter-thread communication between a worker thread and Event dispatcher thread.
Since the EDT thread is most important in Swing and is responsible for listening event and updating GUI, you must not do any time-consuming task on it, otherwise, you risk your application becoming unresponsive or frozen. Another key thing to note, while using multi-threading in Swing development is that, not only GUI components but there model e.g. TableModel for JTable, must be updated in Event Dispatcher thread. One of the crucial difference between AWT and Swing is that AWT components are thread-safe
Summary
Here is a summary of our discussion, which is also a list of Java Swing best practices in a multithreading environment. When you use threads in Swing development, you risk deadlock and frozen GUI. By following these simple rules, you minimize your chances of errors.
1) Since Swing components are not thread-safe, until any specifics are mentioned in Javadoc, they must be created and modified from AWT Event Dispatcher thread.
2) Not only Swing components but also there model e.g. ListModel, TableModel must be modified from Event Dispatcher thread.
3) AWT Event Dispatcher thread is responsible for updating GUI and listening events, so don't block them by doing time-consuming task there.
4) You can use java.awt.EventQueue's isDispatchThread() or SwingUtilities.isEventDispatchThread() to check if current thread is EDT.
5) Use SwingWorker to perform a lengthy time-consuming tasks in a worker thread.
6) Use InvokeAndWait() and invokeLater() to update GUI components from threads other than the Event Dispatcher thread.
That's all on Why Swing is not thread-safe in Java, more important what does it mean by Swing is not thread-safe. We have also touched base on the Event Dispatcher thread, SwingWorker, invokeAndWait, and invokeLater. This is an extremely important topic from the Swing development and Interview point of view. I have never seen a Java Swing Interview, without any question from threading.
Hello Javin,
ReplyDeleteone thing that bugs me is your writing: you write "there" instead of "their", as in:
"not only GUI components but there model"(should be "their").
Apart from that "grammar nazi thingy" - yet another excellent article, keep up the marvellous work! :)
One question: could you please add answer to which operations in Swing are thread-safe, if there are any? If I understand correctly, only the EDT operations are thread-safe, right? Best regards!
Hello Thasar, Apologies for that mate, had to review it more carefully. Regarding your questions, repaint() and revalidate() are thread safe methods in Swing API. You can call them from any thread.
ReplyDeleteNo need to apologies :) thank You for the answer, and once again ( I can't stress that enough) - excellent article(s)!
ReplyDeleteALL your post are truly exceptional but is there is anyway i can download all these blogs and read as pdf or word doc.
ReplyDeleteOr is there is any index for this blog which can be used .. because all java blogs are tremendous ! hats off !
EDT - Event Dispatch Thread :)
ReplyDelete