1. 程式人生 > >使用多執行緒出現: java.util.ConcurrentModificationException的問題。

使用多執行緒出現: java.util.ConcurrentModificationException的問題。

     在一個批量Insert業務中,使用多執行緒進行約束insert。其中出現的一個問題。

 

     部分資料是成功insert的。 百度得知此問題發生的原因是:在迴圈迭代中,如果對Vetor、ArrayList進行修改,就可能對丟擲這個異常。仔細錯誤檢查程式碼:entryList的作用域過大,並且,在後面做了entryList.clear的操作。物件還是那個物件,只是把裡面的元素清空了而已。

仔細錯誤檢查程式碼

                    List<InStorageMissionEntry> entryList = new ArrayList<InStorageMissionEntry>();

                    for (String billno : fbillnos) {                         InStorageMission mission = setMission(user);                         //entryList = new ArrayList<InStorageMissionEntry>();                         for (PurReceiveOrder purReceiveOrder : purReceiveOrderList) {                                                          String fbillno = purReceiveOrder.getFbillno();                             if(billno.equals(fbillno)) {                                                                 mission.setRecOrgId(purReceiveOrder.getRecOrgId());                                 mission.setRecOrgNumber(purReceiveOrder.getRecOrgNumber());                                                                                                  InStorageMissionEntry setEntry = setEntry(user,purReceiveOrder);                                 entryList.add(setEntry);                                                                  Integer Fid = purReceiveOrder.getfId();                                 Map<String,Integer> map = new HashMap<String, Integer>();                                                                  map.put("billId", Fid);                                 map.put("entryId", purReceiveOrder.getEntryId());                                 map.put("missionStatus", 3);                                 mapList.add(map);                             }                         }                         System.out.println("entryList====="+entryList.size());                         if(mission!=null && entryList !=null && entryList.size()>0) {                             try {                                 synchronized (this) {                                     inStorageMissionService.insertInStorageMission(mission, entryList);                                     msg = new Msg();                                     msg.setCode(100);                                     msg.setMsg("");                                     msg.setObject(mission);                                     msgList.add(msg);                                     mission=null;                                     entryList.clear();
                                }                             } catch (Exception e) {                                 e.printStackTrace();                                 return Msg.defineFail("")+"";                                                              }                         }                     }

         修改後的正確程式碼應該是:

                       List<InStorageMissionEntry> entryList =null;                     for (String billno : fbillnos) {                         InStorageMission mission = setMission(user);                         entryList = new ArrayList<InStorageMissionEntry>();                         for (PurReceiveOrder purReceiveOrder : purReceiveOrderList) {                                                          String fbillno = purReceiveOrder.getFbillno();                             if(billno.equals(fbillno)) {                                                                mission.setRecOrgId(purReceiveOrder.getRecOrgId());                                 mission.setRecOrgNumber(purReceiveOrder.getRecOrgNumber());                                                                                              InStorageMissionEntry setEntry = setEntry(user,purReceiveOrder);                                 entryList.add(setEntry);                                                                  Integer Fid = purReceiveOrder.getfId();                                 Map<String,Integer> map = new HashMap<String, Integer>();                                                                  map.put("billId", Fid);                                 map.put("entryId", purReceiveOrder.getEntryId());                                 map.put("missionStatus", 3);                                 mapList.add(map);                             }                         }                         System.out.println("entryList====="+entryList.size());                         if(mission!=null && entryList !=null && entryList.size()>0) {                             try {                                 synchronized (this) {                                     inStorageMissionService.insertInStorageMission(mission, entryList);                                     msg = new Msg();                                     msg.setCode(100);                                     msg.setMsg("成功");                                     msg.setObject(mission);                                     msgList.add(msg);                                     mission=null;                                     //entryList.clear();                                 }                             } catch (Exception e) {                                 e.printStackTrace();                                 return Msg.defineFail("錯誤")+"";                                                              }                         }                     }

      在第一次for迴圈中,重新new了一個entryList,這是個全新的entryList,同時不用再使用entryList.clear()對其清空。因此就不存在修改了ArrayList。

總結:

      程式碼簡介之美還得多學學,多看看啊。雖然java的JC機制幫我們做了很多垃圾回收工作,但是在程式中也應該儘量慎重選擇物件的作用域。作用域能小則小,過了那個作用域,物件的引用為空了,JC就對其進行回收,記憶體的堆區不必因為存在太多物件而佔用記憶體。