In Swing, the GUI is supposed to be updated by the EDT only, since the GUI components are not thread safe.
My question is, if I have a single thread, other than the EDT, that is dedicated to update a specific component, and this component is not accessed by any other thread in my program, only this dedicated thread, is it ok? In my case I have a JTable
and a thread receives information from the network and updates the table (without using EventQueue.invokeLater
). All the other components are updated from the EDT. I have not seen a problem so far, and I was wondering if a bug will surface eventually.
UPDATE
My purpose was to update the table in real-time. The data come constantly from the network and for this I dedicated 1 thread just for the table, to update it constanlty as they come. If I use the SwingUtilities.invokeLater, this means that the table will be updated when the EDT is available. Is not swing supposed to be used for real-time update requirements?
There are a few methods documented as thread-safe. I believe a few less in JDK7, because it turns out some of them are unimplementable as thread-safe. For the most part Swing is thread-hostile - it has to be used from the AWT EDT thread. This is largely because it uses EventQueue.invokeLater
internally at "random". Also there is hidden shared state (you can change the PL&F without having to tell each component for instance). Some classes you may be able to treat as thread-agnostic, but they are not documented as such.
So the answer is, always use the EDT for Swing. As with most threading bugs, you might seem to get away with it and then suddenly fail in production. The bug is likely to be difficult to diagnose and reproduce (particularly if it only happens in production on certain systems). Fixing a code base that is severely broken may not be fun. Keep it clean from the start.
Instead of trying to reason about whether it will or won't work, I would just stick to the well-known 'rule' which is that you should only interact with GUI components using the event dispatching thread. When you receive data from the network, just update the table using SwingUtilities.invokeLater
(or invokeAndWait
).
You might not see problems straight away, but it's quite possible you might do in the future.
You must update GUI components on the EDT. Period. (There are a couple of legacy exceptions to this rule - but they were all silently putting things over to the EDT anyway). The EDT operates as a message pump (as most windowing systems do) - you have to live within that constraint if you want to update GUI components.
If you want your table to update quickly, keep the EDT clean - don't put any huge load onto it.
If you are working with updating live tables, I strongly recommend that you take a look at GlazedLists - they have a very, very good SwingThreadProxyList implementation that takes care of efficiently posting updates to the EDT. You have to agree to drink the GlazedLists koolaid to go this route, but it is mighty tasty koolaid (I love GL).
Is not Swing supposed to be used for real-time update requirements?
No. You may be able to update your data model at a sufficient rate, but the GUI is typically subordinate. You may be able to take advantage of any network latency in your environment. Alternatively, you may need to consider something like Oracle's Sun Java Real-Time System.
You can improve the "liveness" of the EDT by keeping updates brief and using the minimal, correct synchronization. Several alternatives are discussed here.
It is an absolute rule, unless you want race conditions. The event dispatch thread is fast enough for our CCTV app's display not to need hacks.