Guava MultiMap und ConcurrentModificationException

8

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:

%Vor%

und so benutzt:

%Vor%

und so (Ich habe versucht, diesen Teil auf der Karte zu synchronisieren, aber ohne Erfolg)

%Vor%     
Antoine Claval 15.10.2009, 12:53
quelle

5 Antworten

1

In Java8 können Sie auch einen Lambda-Ansatz verwenden:

eventMultiMap.entries().removeIf(genericEventCommandEntry -> genericEventCommandEntry.getValue().equals(command));

    
Evgeny Kiselev 11.05.2017, 18:31
quelle
11

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%     
MHarris 15.10.2009 12:56
quelle
4

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.

    
Jared Levy 04.11.2009 03:37
quelle
4

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.

    
Dimitris Andreou 23.01.2010 00:50
quelle
1

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.

%Vor%     
Mr. Polywhirl 14.12.2013 01:18
quelle