Here is my problem:
This piece of code throws a java.util.ConcurrentModificationException
, because the Vector
listeners
is modified while there exists an Iterator
for this data structure.
The java-doc says that this container offers only a fail-fast iterator.
Is there a possibility to get an Iterator
over a standard container like Vector
or List
in Java that offers me an Iterator
, that does not get invalid (is not fail-fast), if there is an element removed during that Iterator
"lives"?
I should have the same behavior like the std::list
in C++. There the iterator is always valid even if the current iterator is remove. Than the iterator is set to the next element in the list.
public class ClientHandle {
private final Vector<ClientHandleListener> listeners = new Vector<ClientHandleListener>();
public synchronized void addListener(ClientHandleListener chl) {
listeners.add(chl);
}
public synchronized void removeListener(ClientHandleListener chl) {
listeners.remove(chl);
}
private void fireConnectionClosed() {
final ClientHandle c = this;
final Iterator<ClientHandleListener> it = listeners.iterator();
new Thread(){
@Override
public void run() {
while (it.hasNext()) {
it.next().connectionClosed(c); //FIXME the iterator gets modified
}
};
}.start();
}}
public class ClientHandlePool implements ClientHandleListener, TaskManagerListener {
/*...*/
public synchronized void removeClientHandle(ClientHandle ch) {
//here the listeners Vector from the ClientHandle gets modified
ch.removeListener(this);
ch.removeListener(currentListener);
clientHandles.remove(ch);
}
@Override
public void connectionClosed(ClientHandle ch) {
removeClientHandle(ch);
}
}
As far as I know there's no way to retroactively add that ability to any default Collection
implementation (Iterable
in fact).
But there are implementations that support that kind of behaviour by having well-defined responses to concurrent modification while iterating.
One example is the CopyOnWriteList
.