即使我使整个程序的所有方法都同步(包括静态方法和ConcurrentModificationException
方法),我得到main
。
我没有隐藏的迭代器。
答案 0 :(得分:6)
ConcurrentModificationException
可能是由相同的线程在迭代时操纵集合引起的Iterator.remove()
或ListIterator.add()
方法答案 1 :(得分:3)
当您在一个集合上进行迭代时会遇到此异常,在此期间您将从此集合中删除一个条目。
e.g。
Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b"));
for (Object o : objects) {
objects.remove(o); //throws exception
}
您必须将要删除的内容添加到另一个集合中,并在完成对列表的迭代后删除它们。 否则,通过iterator()迭代对象集合,并在当前迭代器上调用remove()。
答案 2 :(得分:3)
ConcurrentModificationException与同步无关。
它与在迭代时修改集合有关。正如Lie Ryan指出的那样,完整的堆栈跟踪将帮助我们指出你是如何得到它的。
通常,为了解决这个问题,你不能在迭代它时修改集合本身。
答案 3 :(得分:3)
如果你运行
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();
答案 4 :(得分:3)
嗯,首先,如果你看到它,它是可能的:如果鸟书和鸟不同意,相信鸟。
现在,怎么会发生?很难说没有看到你的代码,但异常堆栈跟踪将指向它发生的地方;你怎么看周围的?
一般情况下,当你有明显的并发访问时,就会发生这种情况。当你找到它发生的地方时,问问自己什么线程可以到达那里。
答案 5 :(得分:1)
synchronized方法锁定正在运行的对象实例。
如果对象A和B访问同一个集合,那么A#doStuff和B#doStuff是否同步并不重要 - 它们仍然可以同时执行。
要锁定集合,您可能需要锁定集合本身:方法体中的synchronized(集合)或Java 5互斥体(更好)。
(即使在其他人指出的单个线程中你也可以拥有ConcurrentModificationException)。
答案 6 :(得分:1)
ConcurrentModificationException的javadoc包含答案:
请注意,此异常并不总是表示某个对象已被不同的线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。
解决问题的方法是不这样做。
即,(正如其他人所说)如果需要同时进行迭代和修改,请使用迭代器提供的方法,而不是直接修改集合。