Domanda

Ecco il mio problema:

Questo pezzo di codice genera un java.util.ConcurrentModificationException, perché il Vector listeners viene modificato, mentre esiste un Iterator per questa struttura dati. Il java-doc dice che questo contenitore offre solo un iteratore fail-fast.

C'è la possibilità di ottenere un Iterator su un contenitore standard come Vector o List in Java che mi offre un Iterator, che non ottiene non valido (non è fail-veloce), se v'è un elemento rimosso durante quel Iterator " vive "?

dovrei avere lo stesso comportamento come la std::list in C ++. C'è l'iteratore è sempre valida anche se l'iteratore corrente è rimuovere. Che l'iteratore è impostato per l'elemento successivo nell'elenco.

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);
    }
}
È stato utile?

Soluzione

Per quanto ne so non c'è modo di aggiungere retroattivamente che la capacità di qualsiasi implementazione predefinita Collection (Iterable appunto).

Ma ci sono implementazioni che supportano questo tipo di comportamento da avere risposte ben definiti ai modifica concomitante mentre iterazione.

Un esempio è il CopyOnWriteList .

Altri suggerimenti

In caso di ascoltatori, si potrebbe pensare di utilizzare java.util.concurrent.CopyOnWriteArrayList come si deve in genere molto più letture di scrittura.

dare un'occhiata al pacchetto di java.util.concurrent troverete tutto il necessario.

Un modo pigro per creare un veloce, iteratore fail-safe: prendere una copia della lista come un array mentre bloccato, e foreach () sopra la matrice, mentre sbloccato ... Può essere fatto con qualsiasi tipo di 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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top