Pregunta

Aquí está mi problema:

Esta pieza de código lanza una java.util.ConcurrentModificationException, porque el Vector listeners se modifica mientras existe una Iterator para esta estructura de datos. El java-doc dice que este contenedor sólo ofrece un iterador de fail-fast.

¿Existe la posibilidad de obtener una Iterator sobre un contenedor estándar como Vector o List en Java que me ofrece una Iterator, que no recibe no válido (no es a prueba de rápido), si hay un elemento eliminado durante ese Iterator " vidas "?

Yo debería tener el mismo comportamiento como el std::list en C ++. Allí, el iterador es siempre válida incluso si el repetidor actual se quite. Que el iterador se establece en el siguiente elemento de la lista.

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);
    }
}
¿Fue útil?

Solución

Por lo que yo sé que no hay manera de añadir retroactivamente esa capacidad de cualquier implementación Collection defecto (Iterable de hecho).

Sin embargo, existen implementaciones que soporte ese tipo de comportamiento por tener respuestas bien definidas a la modificación concurrente, mientras que la iteración.

Un ejemplo es el CopyOnWriteList .

Otros consejos

En el caso de los oyentes, se podría pensar en usar java.util.concurrent.CopyOnWriteArrayList como lo hace normalmente tiene forma más lecturas que escrituras.

have a look at java.util.concurrent package you will find everything you need.

A lazy way to create a fast, fail-safe iterator: take a copy of the list as an array while locked, and foreach() over the array while unlocked... Can be done with any type of List

private void fireConnectionClosed() {
   final ClientHandle c = this;

   final ClientHandleListener[] listenersArr;
   synchronized(this) {
       listenersArr=listeners.toArray(new ClientHandleListener[0]);
   }
   new Thread(){
       @Override
       public void run() {
          for(ClientHandleListener listener : listenersArr )
              listener.connectionClosed(c);
          }
       };
   }.start();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top