私は2つのアクセサメソッドと通知機能を持つArrayListを持っています。マイリスト:ArrayList iterator throw ConcurrentModificationException
private final List<WeakReference<LockListener>> listeners = new ArrayList<>();
すべての操作は、これを使用して購読する:
public void subscribe(@NonNull LockListener listener) {
for (Iterator<WeakReference<LockListener>> it = listeners.iterator(); it.hasNext();) {
// has this one already subscribed?
if (listener.equals(it.next().get())) {
return;
}
}
listeners.add(new WeakReference<>(listener));
}
すべて配信停止の操作は、この使用:
public void unsubscribe(@NonNull LockListener listener) {
if (listeners.isEmpty()) {
return;
}
for (Iterator<WeakReference<LockListener>> it = listeners.iterator(); it.hasNext();) {
WeakReference<LockListener> ref = it.next();
if (ref == null || ref.get() == null || listener.equals(ref.get())) {
it.remove();
}
}
}
と通知を:私は「何
private void notifyListeners() {
if (listeners.isEmpty()) {
return;
}
Iterator<WeakReference<LockListener>> it = listeners.iterator();
while (it.hasNext()) {
WeakReference<LockListener> ref = it.next();
if (ref == null || ref.get() == null) {
it.remove();
} else {
ref.get().onLocked();
}
}
}
私のテストで見ると、nのit.next() otifyListeners()は時々ConcurrentModificationExceptionをスローします。私の推測では、これはsubscriberメソッドのlisteners.add()によるものです。
私はここでイテレーターの誤解があったと思います。私はリストを反復することで、追加/削除操作によって引き起こされる並行性の問題から私を保護していたという仮定の下にいました。
明らかに私はここで間違っています。反復子は、反復処理中のコレクションを変更する際にConcurrentModificationExceptionから保護されるだけですか?たとえば、反復中にリスト上でremove()を呼び出すとエラーがスローされますが、it.remove()は安全です。
私の場合、サブスクライブするのは、反復されているのと同じリスト上でadd()を呼び出すことです。私の理解は正しいのでしょうか?
イテレータのドキュメントを読んでいる場合は、基本構造を変更できないことがわかります – efekctive