質問

ここに私の問題は、次のとおりです。

このデータ構造のためにjava.util.ConcurrentModificationExceptionが存在しながらVectorlistenersが変更されるので、

は、コードのこの部分は、Iteratorをスロー。 Javaの-docのは、唯一のフェイルファスト反復子このコンテナの提供と言っています。

JavaでIteratorまたはVectorなどの標準コンテナの上にListを取得する可能性があることを申し出、私Iterator、不正な取得していないこと(フェイルファストされていない)、そのIterator時に除去要素がある場合には、「命 "?

私はC ++でstd::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);
    }
}
役に立ちましたか?

解決

私の知る限りでは遡及的に任意のデフォルトのCollectionの実装(実際にはIterable)にその機能を追加する方法はありません。

しかし、実装があることを反復しながら、同時変更に明確に定義された応答を持つことにより、行動の支援そういうます。

一例は CopyOnWriteList

他のヒント

リスナーの場合は、あなたは、通常より多くの書き込みより読み込みの方法を持っているようjava.util.concurrent.CopyOnWriteArrayListを使用して考えるかもしれません。

あなたはあなたが必要なすべてを見つけるでしょうjava.util.concurrentパッケージを見てます。

の高速を作成するための怠惰な方法は、フェイルセーフのイテレータ:ロックを解除しながら、アレイの上にロックされている間配列としてリストのコピーを取り、foreachの()を... <リストの任意のタイプで行うことができます/ P>

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();
}
scroll top