Ich verstehe nicht, warum ich eine ConcurrentModificationException erhalte, wenn ich diese multimap
iteriere.
Ich lese die folgende Eintrag , aber ich bin mir nicht sicher, ob ich die ganze Sache verstanden habe.
Ich habe versucht, einen synchronisierten Block hinzuzufügen. Aber mein Zweifel ist, was zu synchronisieren ist und wann.
Das multimap
ist ein Feld und wurde wie folgt erstellt:
und so benutzt:
%Vor%und so (Ich habe versucht, diesen Teil auf der Karte zu synchronisieren, aber ohne Erfolg)
%Vor%In Java8 können Sie auch einen Lambda-Ansatz verwenden:
eventMultiMap.entries().removeIf(genericEventCommandEntry -> genericEventCommandEntry.getValue().equals(command));
Das Aufrufen von remove für eine Auflistung, während Sie sie durchlaufen, führt jedes Mal zu einer ConcurrentModificationException, auch wenn sie alle im selben Thread ausgeführt wird - die richtige Sache ist ein expliziter Iterator und Aufruf von .remove () .
Bearbeiten: Ändern Sie Ihr Beispiel:
%Vor%Wenn ein anderer Thread Ihre Multimap ändern könnte, während diese Logik ausgeführt wird, müssen Sie dem MHarris-Code einen synchronisierten Block hinzufügen:
%Vor%Oder Sie können den Iterator wie folgt weglassen,
%Vor%Der Aufruf removeAll () erfordert keine Synchronisierung. Wenn Sie den synchronisierten Block jedoch auslassen, könnte die Multimap zwischen dem Aufruf removeAll () und einem der Aufrufe von size () mutieren, was zu einem falschen Wert von nbRemoved führt.
Wenn Ihr Code jetzt single-threaded ist und Sie nur einen ConcurrentModificationException-Aufruf vermeiden möchten, können Sie die Multimaps.synchronizedMultimap- und synchronized (eventMultimap) -Logik weglassen.
Vielleicht möchten Sie diesen Blogpost für eine weitere Fallstricke sehen, die ConcurrentModificationException
beim Durchlaufen einer Multimap, ohne dass ein anderer Thread interferiert. Kurz gesagt, wenn Sie die Schlüssel von multimap durchlaufen, greifen Sie auf die jeweilige Sammlung von Werten zu, die jedem Schlüssel zugeordnet sind, und entfernen Sie einige Elemente aus einer solchen Sammlung, wenn das Element der letzte der Sammlung ist, zu dem Sie gehen werden Haben Sie ConcurrentModificationException
, wenn Sie versuchen, auf den nächsten Schlüssel zuzugreifen - weil das Leeren einer Sammlung das Entfernen des Schlüssels auslöst und somit den Keyset der Multi-Map strukturell verändert.
Ich bevorzuge Multimap.values().iterator()
, wenn Sie sich nicht um den Schlüssel kümmern. Sie sollten auch versuchen, möglichst keine synchronen Blöcke zu verwenden, da Sie Lese- / Schreibvorgänge nicht effektiv priorisieren können.
Tags und Links java concurrency guava concurrentmodification multimap