2

があり、このセットの値をループConcurrentSKipListSetで反復処理しています。for-eachある時点で、別のスレッドがこのセットから要素を削除しようとしています。

1 つのスレッドが、まだ反復処理を行っていない (または反復処理を開始したばかりの) 要素を削除し、ループ内からの呼び出しが失敗する状況に陥っていると思います。

わかりやすくするためのコード:

for(Foo foo : fooSet) {
  //do stuff

  //At this point in time, another thread removes this element from the set

  //do some more stuff
  callService(foo.getId()); // Fails
}

ドキュメントを読んでも、これが可能かどうかはわかりません:

イテレータは弱一貫性であり、イテレータの作成時または作成後のある時点でのセットの状態を反映する要素を返します。それらは をスローせずConcurrentModificationException、他の操作と同時に進行する場合があります。

これは可能ですか?もしそうなら、これを処理する良い方法は何ですか?

ありがとう

意思

4

2 に答える 2

0

私は、異なるスレッドによって読み書きされるキューでも、この問題に遭遇しました。1 つのアプローチは、不要になった要素を削除する代わりにマークすることです。リスト全体を調べた後、クリーンアップ イテレータを実行できます。リストから要素を削除するためだけにグローバル ロックが必要であり、残りの時間はコードを並行して実行できます。概略的には、次のように機能します。

writer:
  while() {
    set.add(something);
    something.markForDelete();
  }

reader:
  while() {
    // process async
    iterator iter = set.getIterator();
    for(iter.hasNext()) {
      ... work, check isMarkedForDelete() ...
    }
    iter = set.getIterator();

    // delete, sync
    globalLock.Lock();
    for(iter.hasNext()) {
      if(something.isMarkedForDelete()) {
      set.remove(something);
    }
    globalLock.Unlock();
  }
}
于 2013-09-13T13:15:42.357 に答える