修正Collection
ということを反復しながら、Collection
使用がIterator
されて許可されていないのほとんどがCollection
クラス。Javaライブラリーは、Collection
「並行変更」と繰り返し実行しながら、aを変更する試みを呼び出します。残念ながら、唯一の考えられる原因は複数のスレッドによる同時変更であることが示唆されていますが、そうではありません。1つのスレッドのみを使用してCollection
(Collection.iterator()
、または拡張for
ループを使用して)のイテレータを作成し、反復を開始(を使用Iterator.next()
、または拡張for
ループの本体に入る)し、を変更してCollection
、反復を続行できます。
プログラマーを支援するために、これらのクラスの一部の実装は、誤った並行変更を検出しようとし、それを検出した場合にをスローします。ただし、一般に、すべての同時変更の検出を保証することは不可能であり、実用的ではありません。したがって、を誤って使用しても、常にスローされるとは限りません。Collection
ConcurrentModificationException
Collection
ConcurrentModificationException
のドキュメントはConcurrentModificationException
言う:
この例外は、オブジェクトの同時変更が許可されていないときに、オブジェクトの同時変更を検出したメソッドによってスローされる場合があります...
この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示すわけではないことに注意してください。単一のスレッドがオブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行した場合、オブジェクトはこの例外をスローする可能性があります...
フェイルファストの動作は保証されないことに注意してください。これは、一般的に言えば、非同期の同時変更が存在する場合にハードな保証を行うことは不可能であるためです。フェイルファースト操作ConcurrentModificationException
は、ベストエフォートベースでスローされます。
ご了承ください
文書HashSet
、HashMap
、TreeSet
およびArrayList
クラスがこれを言います:
[このクラスから直接または間接に]返されたイテレータはフェイルファストです。イテレータの作成後、イテレータ自身のremoveメソッド以外の方法で[コレクション]が変更されると、Iterator
スローによってがスローされますConcurrentModificationException
。したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定的な動作の危険を冒すのではなく、迅速かつ完全に失敗します。
イテレータのフェイルファスト動作は、同期していない同時変更が存在する場合、一般的に言えば、厳密な保証を行うことが不可能であるため、保証できないことに注意してください。フェイルファストイテレータConcurrentModificationException
は、ベストエフォートベースでスローします。したがって、この例外に依存して正確であるプログラムを作成するのは誤りです。反復子のフェイルファスト動作は、バグを検出するためにのみ使用する必要があります。
動作は「保証できません」であり、「ベストエフォートベース」にすぎないことに注意してください。
Map
インターフェイスのいくつかのメソッドのドキュメントはこれを言います:
非並行実装では、このメソッドをオーバーライドし、ConcurrentModificationException
計算中にマッピング関数がこのマップを変更することが検出された場合は、ベストエフォートベースでをスローする必要があります。並行実装では、このメソッドをオーバーライドし、IllegalStateException
計算中にマッピング関数がこのマップを変更することが検出され、結果として計算が完了しないことが検出された場合、ベストエフォートベースでをスローする必要があります。
検出には「ベストエフォートベース」のみが必要ConcurrentModificationException
であり、非並行(スレッドセーフではない)クラスに対してのみ明示的に推奨されることに注意してください。
デバッグ中 ConcurrentModificationException
したがって、によるスタックトレースが表示されたConcurrentModificationException
場合、その原因がへの安全でないマルチスレッドアクセスであるとすぐに推測することはできませんCollection
。あなたは、必要があり、スタックトレースを調べるのどのクラスかを決定するためにCollection
例外を投げた(クラスのメソッドが直接または間接的にそれを投げています)、およびそのためのCollection
オブジェクト。次に、そのオブジェクトをどこから変更できるかを調べる必要があります。
同時変更エラーを防ぐためのプログラミング
可能な場合は、Collection
オブジェクトへのすべての参照を制限してください。これにより、同時変更を防止しやすくなります。作成したオブジェクトまたはローカル変数を、およびへの参照を返さないメソッドから、あるいはそのイテレータ。そうすれば、を変更できるすべての場所を調べるのがはるかに簡単になります。を複数のスレッドで使用する場合は、適切な同期とロックを使用してスレッドのみがアクセスできるようにするのが実際的です。Collection
private
Collection
Collection
Collection
Collection