/ / ConcurrentModificationException auch mit Iterator - Java, Android, Concurrency, Hashmap

ConcurrentModificationException sogar mit Iterator - Java, Android, Nebenläufigkeit, hashmap

Ich verwende eine HashMap und einen Iterator, um die Elemente aus der Karte zu entfernen.

new Handler(SdkContext.getApplicationContext().getMainLooper()).post(new Runnable() {
@Override
public void run() {
synchronized (this) {

Iterator<Map.Entry<Placement, Aunit>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Placement, Aunit> entry = iterator.next();
entry.getValue().deInit();
iterator.remove();
}
}
}
});

Aber auch dieser Code verursacht ConcurrentModificationException Nur manchmal. Es ist sowohl threadsicher als auch ich benutze Iterator ebenfalls. Also, wie kann es die Ausnahme verursachen?

Antworten:

1 für die Antwort № 1

Die meisten Sammlungen / Iteratoren sind nicht threadsicher. Sie scheinen zu versuchen, dies zu umgehen, indem Sie anrufen synchronized. Dies ist keine schlechte Idee, wenn Sie synchronisiert haben jeden Zugriff (Lesen und Schreiben) auf die Sammlung (Ihre map) mit dem gleichen Objekt überwachen.

In Ihrem Beispielcode verwenden Sie this als Monitor / Lock-Objekt (bezogen auf die Instanz Ihrer anonymen inneren Typklasse) Runnable). Das ist nicht angemessen, da Sie nicht dasselbe Objekt verwenden, wenn Sie die Sammlung an einer anderen Stelle bearbeiten: this ist ein anderes Objekt, wenn Sie Ihren Code aufrufen und es wird nicht an den aufrufenden Code übergeben.

Um dies richtig zu machen, müssen Sie synchronisieren jeden Zugang zum map. Und Sie müssen jedes Mal dasselbe Synchronisationsobjekt verwenden (Sie könnten das verwenden map selbst). Vielleicht möchten Sie auch nachlesen, wie die Synchronisation wirklich funktioniert.


0 für die Antwort № 2

Beim Durchlaufen der Karte können wir das nicht ändernStruktur der Karte durch Hinzufügen oder Entfernen der Elemente. Hier versuchen Sie, die Elemente aus der Map zu entfernen, die eine ConcurrentModifactionException auslösen. Hier bekommst du die Synchronisation auf Runnable Objekt aber nicht auf Map. Mit dem folgenden Code erhalten Sie eine synchronisierte Karte, oder Sie können die bereitgestellte ConcurrentMap verwenden.

   Collections.synchronizedMap(map)