虽然用一个线程修改ArrayList并用另一个线程迭代它,但它抛出ConcurrentModificationException
我在下面的代码尝试。虽然用一个线程修改ArrayList并用另一个线程迭代它,但它抛出ConcurrentModificationException
public class IteratorFailFastTest {
private List<Integer> list = new ArrayList<>();
public IteratorFailFastTest() {
for (int i = 0; i < 10; i++) {
list.add(i);
}
}
public void runUpdateThread() {
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 10; i < 20; i++) {
list.add(i);
}
}
});
thread2.start();
}
public void runIteratorThread() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer number = iterator.next();
System.out.println(number);
}
}
});
thread1.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
IteratorFailFastTest tester = new IteratorFailFastTest();
tester.runIteratorThread();
tester.runUpdateThread();
}
}
它有时抛出ConcurrentModificationException并且有时会成功运行。
我不明白的是,因为有2个不同的方法,每个包含一个线程。他们将一一执行。当一个线程完成修改列表时,线程2将开始迭代。
我也提到这个链接(Why no ConcurrentModificationException when one thread iterating (using Iterator) and other thread modifying same copy of non-thread-safe ArrayList),但它是不同的情况。
那么,它为什么抛出这个异常?是因为线程吗?
有人可以解释一下吗?
您正在启动两个线程,然后不再进行同步。
有时,两个线程将同时运行,您将获得CME。其他时候,第一个线程将在第二个线程实际开始执行之前完成。在那种情况下不会得到CME。
你得到这种变化的原因可能归结于你的系统上的负载。或者它可能只是由于线程调度器是非确定性的事实。
与创建/启动线程的开销相比,您的线程实际上只执行少量工作。因此,其中一人可以很快从其run()
方法返回,这并不奇怪。
如果我将它们称为“Thread obj = new Thread()”,那么情况就是这样。 obj.start(); Thread obj2 = new Thread(); obj2.start();”但这些是两种不同的方法。他们将被逐一调用。他们不是吗? –
是的。他们是。但仔细阅读javadoc的'start()'。它们不保证在start()调用返回给调用者的时候,子线程将*运行。事实上,两个'start()'调用使用不同的方法是无关紧要的。 –
请不要链接到代码/文章。编辑您的问题以包含实际的代码片段。 – Bohemian
@Bohemian:我编辑了这篇文章。 –
应该没有CME:迭代器被创建但没有被使用 – Bohemian