ArrayList ConcurrentModificationException and ClassCastException
I have a program in which data objects are held in an ArrayList object. The ArrayList (let's call it myList) is a class attribute. From myList, various graphics and data is drawn onscreen in a GUI.
Modification to myList occurs approximately every second (this could be an addition to the ArrayList, a removeAll action, etc).
The problem is that I keep getting a concurrency error, almost as soon as the GUI loads:
java.util.ConcurrentModificationException - at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
This is at the section where I call my java 5.0 for-loop iterator to display stuff in my GUI from the ArrayList. Having gone to the API, I found http://java.sun.com/j2se/1.4.2/docs/api/java/util/ArrayList.html which describes to use "Collections.synchronizedList" when creating the ArrayLists... so my code would look like:
this.myList = (ArrayList<MyDataObject>) Collections.synchronizedList(new ArrayList<MyDataObject>());
(Note that I needed to add the cast to an ArrayList because I received an error suggesting that a conversion from List to ArrayList was not possible.) However this brings:
Caused by: java.lang.ClassCastException: java.util.Collections$SynchronizedRandomAccessList
I sort of feel I'm going around in loops with this - I can't not use the synchronizedList option because of the concurrency error, but I can't use the synchronizedList option because I need to cast, and that's not allowed.
Has anyone got any advice on this confusing dilemma? :)
# 1
The answer could come from this fragment in specifications:
ConcurrentModificationException:
"Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception. "
It is possible that you do not need sychronization if the list is not accessed by more threads.
As for the class cast. When you call Collections.synchronizedList, the initial list is wrapped into another class that offer the synchronization.
# 2
Look at Iterator.remove() as in:
for (Iterator it = myArrayList.iterator(); it.hasNext(); ) {
MyDataObject mdo = (MyDataObject) it.next();
//do stuff to decide if it is to be removed
it.remove();
}
Or look at the ListIterator - same concept as above.
If your class is being accessed by multiple threads, then you have to go the synchronization route.
3cpoa at 2007-7-10 12:06:52 >

# 3
If you are using swings for GUI, In the javadocs for swings, it is written that call the GUI in
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
/* create and show the GUI */
}
});
It is recommended because it ensures that the GUI won't have a thread-safety problem that could break the UI before it even appears onscreen.
May be this solves your problem.
gssa at 2007-7-10 12:06:52 >

# 4
Just to update, this issue seems to have resolved itself during the course of my checking the program logic (there were a few typos to fix, i.e. where I'd been calling, say, ArrayList1 instead of ArrayList2). I think one of these small errors meant that something like what abc0xyz suggest was happening - that the collection was maybe being changed whilst iterated through by another method....
Thanks - DD are distro'd :)