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 № 1Die 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)