我尝试使用多线程迭代ArrayList
对象,但有时它会给出ConcurrentModificationException
,有时不会?我无法理解这里发生了什么。
我在下面分享我的代码:
import java.util.ArrayList;
import java.util.Iterator;
public class ConcurrentDemo extends Thread{
static ArrayList l=new ArrayList();
public void run()
{
/*
* try { Thread.sleep(2000); } catch(InterruptedException e) { }
*/
System.out.println("child thread updating list");
l.add("D");
System.out.println(l);
}
public static void main(String args[]) throws InterruptedException
{
l.add("A");
l.add("B");
l.add("c");
ConcurrentDemo c=new ConcurrentDemo();
c.start();
System.out.println(l);
Iterator itr =l.iterator();
while(itr.hasNext())
{
String s1=(String)itr.next();
System.out.println("main thread list:" + s1);
Thread.sleep(3000);
}
System.out.println(l);
}
}
请在您的代码中内联查看我的答案:
import java.util.ArrayList;
import java.util.Iterator;
public class ConcurrentDemo extends Thread{
static ArrayList l=new ArrayList();
public void run()
{
System.out.println("child thread updating list");
l.add("D");
System.out.println(l);
}
public static void main(String args[]) throws InterruptedException
{
//----> Main thread starts here
l.add("A");
l.add("B");
l.add("c");
//----> l now contains A,B,C
ConcurrentDemo c=new ConcurrentDemo();
//----> You have started a second thread here
c.start();
//-----> Its not determined, which line will be executed first from now on, as 2 threads are running parallelly, the ConcurrentModificationException most likely occur in cases, when the "l.add("D");" called within the "run();" method AFTER the Iterator has been created.
System.out.println(l);
Iterator itr =l.iterator();
while(itr.hasNext())
{
String s1=(String)itr.next();
System.out.println("main thread list:" + s1);
Thread.sleep(3000);
}
System.out.println(l);
}
}
请注意,关于交互器,如果在迭代过程中以任何方式修改基础集合,而不是通过在迭代器接口上调用适当的方法,则未指定迭代器的行为。参考
而不是在执行此操作时随机失败,该集合很好 足以跟踪它被修改了多少次,并抛出 ConcurrentModificationException 当它检测到并发 修改。参考
如果计划通过添加新元素来修改迭代器的基础集合,请考虑使用 ListIterator
代码示例:
static ArrayList l=new ArrayList();
ListIterator listItr =l.listIterator();
listItr.add(e);
有关更多信息,请查看此 Java 并发和多线程教程。
编辑:由于可能很难注意到,我突出显示了上面代码中最重要的内联注释:
在你调用c.start();
它未确定后,哪一行将首先执行,因为 2 个线程并行运行,当创建迭代器后在run();
方法中调用l.add("D");
时,最有可能发生 ConcurrentModificationException。