番石榴基于和ConcurrentModificationException[重复]
-
21-09-2019 - |
题
这个问题已经有一个答案在这里:
我不明白为什么我得到一个ConcurrentModificationException当我迭代,通过这个 multimap
.我读下 项, 但我不知道,如果我理解整个事情。我想添加一个同步的区块。但我怀疑是什么同步的,而当。
的 multimap
是的一个领域,并创建了这样的:
private Multimap<GenericEvent, Command> eventMultiMap =
Multimaps.synchronizedMultimap(HashMultimap.<GenericEvent, Command> create());
并且用这样的:
eventMultiMap.put(event, command);
像这样(I试图同步的这一部分的地图,但没有成功)
for (Entry<GenericEvent, Command> entry : eventMultiMap.entries()) {
if (entry.getValue().equals(command)) {
eventMultiMap.remove(entry.getKey(), entry.getValue());
nbRemoved++;
}
}
解决方案
在java8你也可以使用一种氧办法:
eventMultiMap.entries().removeIf(genericEventCommandEntry -> genericEventCommandEntry.getValue().equals(command));
其他提示
呼吁删除关于收集当你迭代过它将导致一个ConcurrentModificationException每一次,即使它的所有做相同的线正确的事情要做的就是获得一个明确的迭代和电话。删除()。
编辑:修改的例子:
Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator();
while (i.hasNext()) {
if (i.next().getValue().equals(command)) {
i.remove();
nbRemoved++;
}
}
你可能想看看 该博文 另一个陷阱产生一个 ConcurrentModificationException
当经历的基于没有其他线干扰。在短期,如果你穿越基于的钥匙,访问各自的收集的数值与每个相关的关键,并删除一些元素从这样的收集, 如果这件是最后的集合 你将拥有 ConcurrentModificationException
当你试图进入下一个关键-因为清空一个收集触发器除去的关键,因而从结构上的修改的基于的键集。
如果另外一个线程可以修改的基于虽然这种逻辑正在运行,你需要添加一个同步块MHarris的代码:
synchronized (eventMultimap) {
Iterator<Entry<GenericEvent, Command>> i = eventMultiMap.entries.iterator();
while (i.hasNext()) {
if (i.next().getValue().equals(command)) {
i.remove();
nbRemoved++;
}
}
}
或者,你可以省略的迭代方法如下,
synchronized (eventMultimap) {
int oldSize = eventMultimap.size();
eventMultimap.values().removeAll(Collections.singleton(command));
nbRemoved = oldSize - eventMultimap.size();
}
该removeAll()call不需要同步。然而,如果省略同步块,该基于可能变异之间的removeAll()电话和一个尺寸()呼吁,导致错误的价值nbRemoved.
现在,如果你的代码是单程的,你只是想避免一ConcurrentModificationException打电话,你可以离开了多地图.synchronizedMultimap和同步(eventMultimap)的逻辑。
我更喜欢 Multimap.values().iterator()
如果你不关心的关键。你也应该试试远离使用同步块尽可能的,因为你不能优先考虑读写有效。
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock writeLock = lock.writeLock();
public void removeCommands(Command value) {
try {
writeLock.lock();
for (Iterator<Command> it = multiMap.values().iterator(); it.hasNext();) {
if (it.next() == value) {
it.remove();
}
}
} finally {
writeLock.unlock();
}
}