I have a large quantity of things, a thread that repeatedly iterates over them, and a separate thread that occasionally removes or adds individual things. The things are in a synchronized linked list:
private List<Thing> things = Collections.synchronizedList(new LinkedList<Thing>());
My first thread iterates over them:
while (true) {
for (Thing thing : things) {
thing.costlyOperation();
}
// ...
}
When my second thread adds or removes things, the above iterator blows up with a ConcurrentModificationException
. However, it seems that removal and addition are permissible in my above case. The constraints are that (A) the costlyOperation
method must not be called when a Thing is not present in the list, and (B) should be called promptly (on the current or the next iteration) when a Thing is present, and (C) additions and deletions via that second thread must complete quickly, and not wait.
I might synchronize on things
before I enter my iteration loop, but this blocks the other thread for too long. Alternatively, I can modify Thing
to include an isDead
flag, and perform a nice quick iterator.remove()
loop to get rid of dead things before the loop above, wherein I'd check the flag again. But I want to solve this problem near this for loop, with minimal pollution. I've also considered creating a copy of the list (a form of "fail-safe iteration"), but that seems to violate constraint A.
Will I need to code up my own collection and iterator? From scratch? Am I neglecting to see how the CME is actually a useful exception even in this case? Is there a data structure, strategy, or pattern that I could use, instead of that default iterator, to solve this problem?