質問

このコードは、リストがdosomething()で変更されている場合、同時変更例外をスローします。いくつかの同期ブロックにコードを囲むことでそれを避けることは可能ですか?

List l = Collections.synchronizedList(new ArrayList());

// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
  doSomething(i.next());
}
役に立ちましたか?

解決

  • リストからアイテムを削除している場合、電話してそれを行うことができます iterator.remove() それ以外の list.remove(iterator.next())

  • アイテムを追加している場合 - まあ、反復リストのコピーを作成してそこに追加します

  • 上記のコードスニペットが同じ方法の一部である場合、同期したリストや同期ブロックは必要ありません。他のスレッドはローカルリストにアクセスできません。

他のヒント

君は できる aを変更します Collection あなたがそうするならば、それを繰り返しながら Iterator インターフェース。使用できます Iterator.remove() 要素を削除します。

あなたがそれを繰り返している間にそれを変更することはできません。同期することはここでは役に立ちません。

編集:Iteratorが持っていることを忘れていました remove 方法。したがって、削除することができます。

私は他の人に同意します Iteratorremove().


同期について、同期は相互作用を制御するように設計されていることを追加したかった 異なるスレッド間.

オブジェクトがいくつかの方法を同期させることが典型的なものであり、それは別の方法を呼び出すでしょう。そのため、言語デザイナーは、同じスレッドが同期して自分でブロックされないと判断しました。

また、それについて考えると、それは自分自身を待っている糸がブロックされています、あなたは壮大です 飢star 視点! ;-)

したがって、これはあなたの質問の1つに答えます。コードを同期することで問題を回避することはできません。

使用する CopyOnWriteArrayList 同期された配列リストの代わりに

List l = Collections.synchronizedList(new ArrayList());

synchronized(l) { 
   // normal iteration -- can throw ConcurrentModificationException
   // may require external synchronization
   for (Iterator i=list.iterator(); i.hasNext(); ) {
      doSomething(i.next());
   }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top