How do I avoid java.util.ConcurrentModificationException when accessing a list that is being worked on in another thread (SwingWorker)?
Details on what I'm trying to use:
a GUI class which contains this "main" method and I think should run on the EDT.
public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { new myGUIwithButton(); } }); }This GUI has a paint method that takes a list of
Words,a class containing Strings and coordinates, and shows them :public void paint(final List<Word> words){ SwingUtilities.invokeLater(new Runnable() { public void run() { // prepare GUI's background, then : for(Word word : words){ // <-- this is line 170 in the error shown below // show each word in the GUI // note that I'm not modifying the words list here }When pushing a button in the GUI, an instance of a class extending
SwingWorker<List<Word>,List<Word>>is executed. That creates the working thread as far as I understand. The overriddendoInBackgroundmethod creates a Word list and then publishes it regularly :public List<Word> doInBackground() { List<Word> words = new ArrayList<Word>(); while (!isCancelled()) { // do some work, define aNewWord words.add( aNewWord ); publish(words); Thread.pause(someTime); } return words; }The published words are then automatically sent to the overridden
processmethod:protected void process(List< List<Word> > wordss) { // Executed on EDT ! <3 // I'm taking only the first list that was published to avoid trouble List<Word> words = wordss.get(0); myGUI.paint(words); }
What's the problem?
When the working thread goes "fast" (pause of less than 50ms), I often get an exception for line 170 which is in the paint method (the GUI file is called MotsFleches.java):
Exception in thread "AWT-EventQueue-1" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at MotsFleches$2.run(MotsFleches.java:170)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at org.GNOME.Accessibility.AtkWrapper$5.dispatchEvent(AtkWrapper.java:700)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
It appears that the words list in the paint method is being modified while the EDT is working on it. I'm not modifying it there, so it must be from the other thread?
I thought the list was just a "snapshot" of the words list in the other thread, since it was sent with the publish method. Apparently it's not.
So what should I change to work in the EDT method with such a "snapshot" of the published list from the SwingWorker?
Thanks for any advice you could provide.
Notes
- After the exception, the program keeps running fine. I only would like to make it cleaner.
- I tried looking at Collections.synchronizedList() or even
synchronized (words){...}but all my attempts failed, most probably because I have no notion of what "synchronism" means in this case and how to use it. - Note that the
invokeLaterin the paint method seemed useless at first because I always call it from the EDT, however if I don't use it the first call ofpaintdoesn't work when the GUI is created (is it because it executes before the GUI despite being called after ? - I obviously lack many notions, so details will be really appreciated.