【问题标题】:java.util.ConcurrentModificationException in ArrayList processingArrayList 处理中的 java.util.ConcurrentModificationException
【发布时间】:2013-12-10 13:46:24
【问题描述】:
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)

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

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");
            }
        }
    }

}

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

【问题讨论】:

  • 问题的真正原因似乎不在这些行中。你在负载中做什么?你有没有把一些东西列入清单?

标签: java concurrency arraylist iterator concurrentmodification


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    文档是这样说的:

    请注意,此实现不同步。如果多个线程 同时访问一个 ArrayList 实例,并且至少其中一个 线程在结构上修改列表,它必须同步 外部。 (结构修改是添加或 删除一个或多个元素,或显式调整后备数组的大小; 仅仅设置元素的值不是结构性的 修改。)这通常是通过同步一些 自然封装列表的对象。如果不存在这样的对象, 该列表应使用 Collections.synchronizedList “包装” 方法。这最好在创建时完成,以防止意外 对列表的非同步访问:

       List list = Collections.synchronizedList(new ArrayList(...));
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 2013-08-16
      • 2013-08-26
      • 2020-05-09
      相关资源
      最近更新 更多