Iterator同時修飾例外
-
20-09-2019 - |
質問
このコードは、リストが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
方法。したがって、削除することができます。
私は他の人に同意します Iterator
と remove()
.
同期について、同期は相互作用を制御するように設計されていることを追加したかった 異なるスレッド間.
オブジェクトがいくつかの方法を同期させることが典型的なものであり、それは別の方法を呼び出すでしょう。そのため、言語デザイナーは、同じスレッドが同期して自分でブロックされないと判断しました。
また、それについて考えると、それは自分自身を待っている糸がブロックされています、あなたは壮大です 飢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());
}
}