ダメダメダメ!
単一の脅威のあるタスクでは、Iterator や CopyOnWriteArrayList を使用する必要はありません (パフォーマンス ヒットのため)。
解決策ははるかに簡単です: for-each loop の代わりに正規の for ループを使用してみてください。
Java の著作権所有者 (数年前は Sun、現在は Oracle) によると、for-each ループ ガイドでは、イテレータを使用してコレクションをウォークスルーし、それを非表示にしてコードの見栄えを良くしています。しかし、残念なことに、収益よりも多くの問題が発生したことがわかります。そうでなければ、このトピックは発生しませんでした。
たとえば、次のコードは、変更された ArrayList で次の反復に入るとき、java.util.ConcurrentModificationException につながります。
// process collection
for (SomeClass currElement: testList) {
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
}
}
しかし、次のコードは問題なく動作します。
// process collection
for (int i = 0; i < testList.size(); i++) {
SomeClass currElement = testList.get(i);
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
i--; //to avoid skipping of shifted element
}
}
したがって、コレクションを反復処理するためにインデックス作成アプローチを使用し、for-each ループを避けるようにしてください。これらは同等ではないためです! For-each ループは、コレクションの変更をチェックし、ConcurrentModificationException 例外をスローするいくつかの内部反復子を使用します。これを確認するには、私が投稿した最初の例を使用するときに、出力されたスタック トレースを詳しく見てください。
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at TestFail.main(TestFail.java:43)
マルチスレッドの場合、対応するマルチタスク アプローチを使用します (synchronized キーワードなど)。