Java:ConcurrentModificationException,3个线程,不同的列表,相同的对象

时间:2014-10-04 14:34:51

标签: java multithreading arraylist concurrentmodification

我有以下情况:

在主函数中,如果某个控制器类从我的数据库中检索10个产品对象。它们保存在ArrayList对象中。

之后我创建了三个扩展Runnable的类,并将product-ArrayList赋予每个类到构造函数中。

在每个构造函数中都创建了一个新的本地ArrayList,并添加了product-ArrayList中的对象:

this.products = new ArrayList();
products.addAll(productListParam);

然后我启动三个线程中的每一个,然后迭代它们的本地产品列表并修改它。

我在迭代本地产品ArrayList时遇到ConcurrentModificationException。

为什么会这样?我假设如果我在每个线程中创建一个完整的新列表,我可以在不需要关心其他线程的情况下在本地修改它 - 我是对的吗?或者从本地列表中删除某个对象是否会以某种方式影响pbject,以便其他线程抛出并发修改异常?

实际上堆栈跟踪看起来像:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at com.x.y.class.method(Classname.java:326)

和326的Classname.java看起来像:

325:List<Product> productsToDelete = new ArrayList();
326:for(Product p: products){
        ...
        if(xy){
              productsToDelete.add(p);
        }
    }
    products.removeAll(productsToRemove);

也许有人暗示我做错了什么?

编辑:在循环内部,产品对象p仅用于阅读。此外,没有对products-ArrayList进行任何修改。它们只被添加到第二个“去除”中。列表在for循环结束后删除它们。我编辑了上面的代码。

我认为我对这个问题最感兴趣,如果我可以创建多个列表对象,通过addAll()方法向每个列表对象添加相同的产品对象,然后可以在每个对象中添加任何内容线程没有关心其他线程?!

2 个答案:

答案 0 :(得分:3)

您无法在迭代其元素的增强型for循环内修改Collection。即使你只有一个线程也不行。

您没有在增强的for循环中包含代码,但如果您需要在其中执行的操作是从列表中删除元素,则可以使用显式迭代器。

Iterator<Product> iter = products.iterator();
While (iter.hasNext() {
    Product p = iter.next();
    ....
    if (some condition)
        iter.remove();
    ....
}

答案 1 :(得分:0)

很抱歉打扰你的人,我初学错误了!

我稍后从其他一些代码基础手动设置了所提到的产品 -ArrayList,并覆盖了新的ArrayList ..所以所有线程只使用了一个ArrayList并发生了ConcurrentModificationException。

正如您在此示例中所看到的,请务必仔细检查您的代码:)

很抱歉打扰你..