我尝试使用多线程迭代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);
}
}
请注意,关于迭代器,如果在迭代过程中以除调用 Iterator 接口(interface)上的适当方法之外的任何方式修改底层集合,则迭代器的行为是未指定的。 Reference
Instead of randomly failing when you do this, the collection is nice enough to keep track of how many times it's been modified, and throw ConcurrentModificationException when it detects concurrent modification. Reference
如果您计划通过添加新元素来修改迭代器的基础集合,请考虑使用 ListIterator
您的代码示例:
static ArrayList l=new ArrayList();
ListIterator listItr =l.listIterator();
listItr.add(e);
有关更多信息,请查看此 Java Concurrency and Multithreading tutorial 。
编辑:
由于可能很难注意到,我突出显示了上面代码中最重要的内联注释:
调用c.start();
后,不确定先执行哪一行,因为2个线程并行运行,ConcurrentModificationException最有可能发生在以下情况:l.add("D");
在 创建迭代器之后在 run();
方法中调用。
关于java - 使用多线程向 ArrayList 添加元素时,有时会给出 ConcurrentModificationException,有时则不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59265410/