java.util.ConcurrentModificationException in ArrayList processing

99封情书 提交于 2020-01-06 15:14: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)

I am getting above mentioned Exception and source code is below:

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

}

I have seen the related questions but they doesn't meet my scenario so i was hoping that if someone can point out the real cause why this is happening.


回答1:


ArrayList is not synchronized. This means that in your TimerThread something else is modifying the ArrayList.

Here's what the docs say:

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

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

Wrapping this list using Collections.synchronizedList() should fix the problem.




回答2:


If load is making changes to the ArrayList while you're using an Iterator, then yes, you're going to get a ConcurrentModificationException as it leaves the iterator in an unknown state.

Lists have a second iterator (ListIterator, which can be fetched with .listIterator()) that can be used to make changes while iterating. Note that this only applies to changes made through the iterator... changes made outside the iterator are still going to have this issue.

CopyOnWriteArrayList is guaranteed to not throw ConcurrentModificationException from its iterators, as it's thread-safe and changes make a new copy... but the iterator also won't be aware of any changes you've made.



来源:https://stackoverflow.com/questions/20199760/java-util-concurrentmodificationexception-in-arraylist-processing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!