ich in regelmäßigen Abständen wollen Löschen einen ConcurrentHashMap
iterieren während Einträge zu entfernen, wie folgt aus:Iterate über ConcurrentHashMap während Einträge
for (Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator(); iter.hasNext();) {
Entry<Integer, Integer> entry = iter.next();
// do something
iter.remove();
}
Das Problem ist, dass ein anderer Thread aktualisieren können oder Werte zu modifizieren, während ich laufen. Wenn das passiert, können diese Updates für immer verloren gehen, weil mein Thread nur veraltete Werte während der Iteration sieht, aber der remove()
wird den Live-Eintrag löschen.
Nach einiger Überlegung kam ich mit dieser Problemumgehung oben:
map.forEach((key, value) -> {
// delete if value is up to date, otherwise leave for next round
if (map.remove(key, value)) {
// do something
}
});
Ein Problem dabei ist, dass es keine Änderungen an veränderbaren Werte fangen, die equals()
(wie AtomicInteger
) nicht implementieren. Gibt es einen besseren Weg, um mit gleichzeitigen Änderungen sicher zu entfernen?
Warum nicht den Eintrag entfernen, bevor Sie irgendwelche Arbeiten ausführen. –
@ClaudioCorsi, die die Tatsache nicht ändern, dass ich eine veraltete Version eines gelöschten Eintrags sehe. – shmosel
Das Problem besteht darin, dass Sie wissen müssen, was seit dem Beginn der Iteration durch die Karte aktualisiert wurde. Auch wenn Sie wissen, welche Objekte aktualisiert wurden. Es ist immer noch möglich, dass ein anderer Thread einen Verweis auf ein Objekt hat, das bearbeitet wurde, das Objekt jedoch nicht aktualisiert wurde. Wird das Objekt wieder hinzugefügt oder wird es gerade aktualisiert? Sollte dieses Objekt einen weiteren Rückruf generieren? –