Guava MultiMap和ConcurrentModificationException

Ant*_*val 9 java concurrency multimap guava concurrentmodification

我不明白为什么在迭代这个时我得到一个ConcurrentModificationException multimap.我读了以下条目,但我不确定我是否理解了整个事情.我试图添加一个synchronized块.但我怀疑的是与什么同步,何时.

multimap是一个字段,创建如下:

private Multimap<GenericEvent, Command> eventMultiMap =   
   Multimaps.synchronizedMultimap(HashMultimap.<GenericEvent, Command> create());
Run Code Online (Sandbox Code Playgroud)

并像这样使用:

eventMultiMap.put(event, command);
Run Code Online (Sandbox Code Playgroud)

并且像这样(我试图在地图上同步这部分,但没有成功)

for (Entry<GenericEvent, Command> entry : eventMultiMap.entries()) {
    if (entry.getValue().equals(command)) {
        eventMultiMap.remove(entry.getKey(), entry.getValue());
        nbRemoved++;
    }
}
Run Code Online (Sandbox Code Playgroud)

MHa*_*ris 11

在迭代它时对集合调用remove将导致每次都出现ConcurrentModificationException,即使它们都在同一个线程中完成 - 要做的事情就是获取一个显式的迭代器并在其上调用.remove().

编辑:修改您的示例:

Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator();
while (i.hasNext()) {
    if (i.next().getValue().equals(command)) {
        i.remove();
        nbRemoved++;
    }
}
Run Code Online (Sandbox Code Playgroud)


Dim*_*eou 5

您可能希望看到此博文中的另一个陷阱,即ConcurrentModificationException在遍历多图时产生一个陷阱,而没有其他线程干扰。简而言之,如果您遍历多重地图的键,请访问与每个键关联的值的相应集合,并从该集合中删除某些元素,如果该元素恰好是ConcurrentModificationException您尝试访问该键时要拥有的集合的最后一个元素下一个键-因为清空集合会触发键的移除,从而在结构上修改了多图的键集。


Evg*_*lev 1

在java8中你还可以使用lambda方法:

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