ConcurrentModificationException
即使我使整个程序的所有方法同步(包括静态方法和方法),我也得到了一个main
。
我没有隐藏的迭代器。
- 这怎么可能呢?!
- 这是什么意思?
- 我该如何解决?
ConcurrentModificationException
即使我使整个程序的所有方法同步(包括静态方法和方法),我也得到了一个main
。
我没有隐藏的迭代器。
ConcurrentModificationException
可能是由同一线程在迭代集合时操作集合引起的Iterator.remove()
orListIterator.add()
方法当您遍历一个集合并在此期间从该集合中删除一个条目时,您会收到此异常。
例如
Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b"));
for (Object o : objects) {
objects.remove(o); //throws exception
}
您必须将要删除的那些添加到另一个集合中,并在完成对列表的迭代后将其删除。否则,您通过它的 iterator() 迭代对象集合并在当前迭代器上调用 remove()。
ConcurrentModificationException 与同步无关。
它与在迭代时修改集合有关。正如 Lie Ryan 所指出的,完整的堆栈跟踪将帮助我们指出您是如何得到它的。
通常,要解决此问题,您不能在迭代集合时修改集合本身。
如果你运行这个
List<Object> list = new ArrayList<Object>();
for(Object obj : list)
list.remove(obj);
你会得到一个商品化。如果不使用适当的函数,则无法在迭代集合时更改它。
这可以使用以下方法解决:
List<Object> list = new ArrayList<Object>();
for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
itr.remove();
好吧,首先,如果你看到它,这是可能的:如果鸟书和鸟不同意,相信鸟。
现在,这怎么可能发生?没有看到你的代码很难准确地说,但是异常堆栈跟踪将指向它发生的地方;你在这附近看到什么?
一般来说,很明显,当你有并发访问时,它就会发生。当你找到它发生的地方时,问问自己有什么线索可以到达那里。
同步方法在它运行的对象实例上放置一个锁。
如果对象 A 和 B 访问同一个集合,那么 A#doStuff 和 B#doStuff 是否同步并不重要——它们仍然可以同时执行。
要锁定集合,您可能需要锁定集合本身:方法主体中的 synchronized(collection) 或 Java 5 互斥锁(更好)。
(正如其他人所指出的那样,即使在单个线程中您也可以拥有 ConcurrentModificationException 的事实)。
ConcurrentModificationException的 javadoc包含答案:
请注意,此异常并不总是表示对象已被不同的线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改了集合,则迭代器将抛出此异常。
解决它的方法是不要那样做。
即,(正如其他人所指出的)如果您需要同时迭代和修改,请使用迭代器提供的方法,而不是直接修改集合。