2015-08-21 88 views
1

我有一个私有类变量,它被声明为ConcurrentModificationException的当迭代通过列表

private List<String> list= new ArrayList<String>(); 

我的应用程序抛出java.util.ConcurrentModificationException当多个线程试图通过列表迭代

for (Iterator i = list.iterator(); i.hasNext();){ 
    System.out.println(i.next()+"\n"); 
} 

我期待建议通过最小的更改来避免此问题。这个类变量被这个类中的多个方法共享和使用。

回答

0

既然你已经有一个线索,该列表将被多个线程访问,声明一个线程安全List

List<String> list= Collections.synchronizedList(new ArrayList<String>()); 
+0

考虑的javadoc听起来像OP需要使用synchronized关键字也明确地同步。所以只是改变这个变量来利用Collections.synchronizedList可能还不够。 – KumarM

1

当你在一个Collection使用iterator,你必须使用iterator.remove()而不是Collection.remove()防止ConcurrentModificationException。但是,如果您有多个线程,则可能还需要使用Collections.syncrhonizedList()

从Oracle的Java文档:

List list = Collections.synchronizedList(new ArrayList()); 
    ... 
synchronized (list) { 
    Iterator i = list.iterator(); // Must be in synchronized block 
    while (i.hasNext()) 
     foo(i.next()); 
} 
+0

谢谢你的回答,但我认为我给了错误的方向。所以所需的场景是多个线程访问这个类,每个线程都使用该列表来存储和检索他们自己的计算。目前私人列表 list = new ArrayList ();将列表放置在由多个线程共享的堆中。我希望每个线程都有自己的列表副本。但是,我们正在获取当前实现的ConcurrentModificationException异常。 – enfany

+0

我不太明白你的意思是每个线程都有自己的副本。当一个线程存储新的东西时应该在其他线程中更新? –

+0

每个线程都会在这个列表中存储不同的结果(因为每个线程都会调用此类中的另一个方法,它将再次使用新的ArrrayList对列表进行初始化)我们希望将此类变量设置为每个线程本地,而不是跨多个线程共享。 – enfany

1

你可以试试CopyOnWriteList,JavaDoc中说:

此数组在迭代器的生存期内不会改变,所以干扰是不可能的,迭代器保证不会抛出ConcurrentModificationException。

List<String> list = new CopyOnWriteArrayList<>(); 
+0

如果大部分活动都是写入,那么我们是否有替代结构来确保线程安全以及避免并发修改异常? – enfany