[java] Annoying error java.util.ConcurrentModificationException
This is basically what I am told:
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:448)
at java.util.AbstractList$Itr.next(AbstractList.java:419)
at java.util.AbstractCollection.remove(AbstractCollection.java:254)
Now, I read the API and it does actually mentioned this Exception. However, I still really can't say what's causing it in my code.. I have an ArrayList, and I add/remove to/from it.
That's basically it.
At a seemingly random time, it decides to crash on me, and print out this exception.
Any known pitfalls and pratfalls here? :)
It means what it says :) You've tried to make two concurrent modifications to the same collection, which usually means:
- You're iterating over a collection in one place, and trying to modify (without using the iterator) it at the same time - usually hidden in some other method.
- You've got two threads that are using the same collection, and one is iterating over while the other modifying it.
The first is usually predictable and easily fixed. The second usually ends up showing up at seemingly random times so that sounds like what you've got this time. Remember that even if you don't actually create and threads yourself you still get other threads in the form of the AWT event handler etc.
- You're iterating over a collection in one place, and trying to modify (without using the iterator) it at the same time - usually hidden in some other method.
- You've got two threads that are using the same collection, and one is iterating over while the other modifying it.
The first is usually predictable and easily fixed. The second usually ends up showing up at seemingly random times so that sounds like what you've got this time. Remember that even if you don't actually create and threads yourself you still get other threads in the form of the AWT event handler etc.
Quote:Original post by OrangyTang
It means what it says :) You've tried to make two concurrent modifications to the same collection, which usually means:
- You're iterating over a collection in one place, and trying to modify (without using the iterator) it at the same time - usually hidden in some other method.
So basically if I have keyboard actions or mouse actions that modify the renderqueue (add/remove) while rendering (iteration)is going on, I'm fucked? :) sounds damn fragile. Since the listeners run on the AWT thread, I guess that indicates the problem of multithreading as well. such lovely business ;)
Oh well. Thanks for the clarification anyways!
The short answer is that you have designed your program wrong if this ever happens and is non-trivial to solve.
Usually, anything that has to iterate over something that might change (e.g. the render thread has to read lots of data from different places) it makes a COPY to iterate over - because if it doesn't then you get effects similar to tearing anyway, so you should NEVER have a problem with the CCME (because your fix to make your rendering prettier avoids this problem).
E.g.
ArrayList readableCopy = (ArrayList) originalList.clone();
Usually, anything that has to iterate over something that might change (e.g. the render thread has to read lots of data from different places) it makes a COPY to iterate over - because if it doesn't then you get effects similar to tearing anyway, so you should NEVER have a problem with the CCME (because your fix to make your rendering prettier avoids this problem).
E.g.
ArrayList readableCopy = (ArrayList) originalList.clone();
Redmilamber, I tried cloning the ArrayList, just to test if that would fix it. It didn't, so I'm still lost I guess.
Right now, the rendering process iterates and calls methods on the cloned arraylist, so that the real list is not modified during iteration anymore.
Right now, the rendering process iterates and calls methods on the cloned arraylist, so that the real list is not modified during iteration anymore.
Did you read the API docs? About half of it deals with concurrent modifications and even tells you how to do it correctly.
API Specification
API Specification
clone() won't work because it only returns a shallow copy of the collection. Which means both copies share the underlying data structure. You have 2 options to overcome this. Use the toArray method and use a for loop to go through the array. Or you can create your own copy:
//initializeArrayList drawList = new ArrayList();//drawingpublic void draw() { drawList.clear(); drawList.addAll(objectList); for(Iterator it=drawList.iterator();it.hasNext();) { //draw it }}
Or you can synchronize on the array list when you modify it. Or better still, create the list as a synchronized collection:
ArrayList myList = (ArrayList)Collections.synchronizedList(new ArrayList());
Better yet, I took a completely different approach and made my own RenderQueue class based off of a primitive array. now, it not only works seamlessly, but it tuned off several milliseconds as well ;) So I am happy again.
Quote:Original post by Aldacron
Or you can synchronize on the array list when you modify it. Or better still, create the list as a synchronized collection:
Yes, except that synchronizing the ArrayList can cause a big performance hit.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement