首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ArrayList处理中的java.util.ConcurrentModificationException

ArrayList处理中的java.util.ConcurrentModificationException
EN

Stack Overflow用户
提问于 2013-11-26 01:45:28
回答 2查看 1.7K关注 0票数 0
代码语言:javascript
复制
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at com.alpha.beta.purchasing.item.VendorItemList.loadItems(VendorItemList.java:51)
at com.alpha.beta.purchasing.Shipment.loadItems(Shipment.java:1006)
at com.alpha.beta.purchasing.Shipment.loadItems(Shipment.java:953)
at com.alpha.beta.purchasing.Shipment.getItemTotal(Shipment.java:1503)
at com.alpha.beta.purchasing.Shipment.getShipmentTotal(Shipment.java:854)
at com.alpha.beta.quickreports.PurchasingGenericListSourceMapper.fillPurchaseReceivingItemListForQuickReportsTask(PurchasingGenericListSourceMapper.java:144)
at com.alpha.beta.quickreports.PurchasingGenericListSourceMapper$2.run(PurchasingGenericListSourceMapper.java:105)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)

我得到了上面提到的异常,源代码如下:

代码语言:javascript
复制
public void loadItems(ArrayList list) {
    if(list != null && list.size() > 0) {
        super.clear();
        Iterator iterator = list.iterator();
        while(iterator.hasNext()) {
            // VendorItem item = (VendorItem)iterator.next();
            //load(new Integer(item.getVendorItemId()), item);

            Object obj = iterator.next(); // << This is where it says exception comes
            if(obj instanceof InvoiceItem) {
                InvoiceItem item = (InvoiceItem)obj;
                load(new Integer(item.getInvoiceItemId()), item);
                //logger.debug("** loading invoice Item " + item.toString());
            }
            else if(obj instanceof PurchaseOrderItem) {
                PurchaseOrderItem item = (PurchaseOrderItem)obj;
                load(new Integer(item.getPoItemId()), item);
                //logger.debug("** loading PO Item " + item.toString());
            }
            else if(obj instanceof ShipmentItem) {
                ShipmentItem item = (ShipmentItem)obj;
                load(new Integer(item.getShipmentItemId()), item);
                logger.debug("** loading ShipmentItem Item " + item.toString());
            }
            //
            else if(obj instanceof VendorItem) {
                VendorItem item = (VendorItem)obj;
                load(new Integer(item.getVendorItemId()), item);
                logger.debug("** loading VendorItem " + item.toString());
            }
            //
            else {
                logger.debug("*** neither invoice/PO/shipment item");
            }
        }
    }

}

我已经看到了相关的问题,但它们不符合我的方案,所以我希望如果有人能指出发生这种情况的真正原因。

EN

回答 2

Stack Overflow用户

发布于 2013-11-26 02:00:28

ArrayList未同步。这意味着在您的TimerThread中,有其他东西正在修改ArrayList。

以下是文档所说的:

请注意,此实现不是同步的。如果多个线程并发访问一个ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部同步该实例。(结构修改是添加或删除一个或多个元素,或显式调整支持数组大小的任何操作;仅设置元素的值不是结构修改。)这通常是通过在自然封装列表的某个对象上进行同步来实现的。如果不存在这样的对象,则应该使用Collections.synchronizedList方法“包装”列表。最好在创建时执行此操作,以防止意外不同步地访问列表:

代码语言:javascript
复制
   List list = Collections.synchronizedList(new ArrayList(...));

使用Collections.synchronizedList()包装这个列表应该可以解决这个问题。

票数 2
EN

Stack Overflow用户

发布于 2013-11-26 02:02:27

如果load在您使用Iterator时对ArrayList进行了更改,那么是的,您将得到一个ConcurrentModificationException,因为它使迭代器处于未知状态。

列表有第二个迭代器(可以用.listIterator()获取的ListIterator),可用于在迭代时进行更改。请注意,这只适用于通过迭代器所做的更改...在迭代器之外所做的更改仍然会有这个问题。

CopyOnWriteArrayList保证不会从它的迭代器中抛出ConcurrentModificationException,因为它是线程安全的,并且更改会生成新的副本……但是迭代器也不会意识到您所做的任何更改。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20199760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档