2014-01-12 121 views
0

我需要幫助,這種情況如下: 我有2個方法:Java錯誤併發修改異常

private void calculateTime(Map.Entry<List<String>, List<LogRecord>> entry, List<LogProcess> processList) { 
    List<List<LogRecord>> processSpentTime = new ArrayList<List<LogRecord>>(); 
    processSpentTime = subListProcess(entry, processSpentTime); 
    for (List<LogRecord> item : processSpentTime) { 
     processList = parse(item, DEFAULT_START_LEVEL); 
    } 
} 

,並在方法calculatime第二種方法

private List<LogProcess> parse(List<LogRecord> recordList, int level) { 
    List<LogProcess> processList = new ArrayList<LogProcess>(); 
    if(!recordList.isEmpty()) { 
     LogProcess process = findProcess(recordList, level); 
     if(!(process instanceof NullLogProcess)) { 
      if(!(process instanceof IncompleteLogProcess)) { 
       processList.add(process); 
      } 

      int fromIndex = recordList.indexOf(process.returnStartIndexOfNextProcess()) + 1; 
      processList.addAll(parse(recordList.subList(fromIndex, recordList.size()), level)); 
     } 
    } 
    return processList; 
} 

public LogProcess findProcess(List<LogRecord> recordList, int level) { 
    LogRecord endRecord = null; 
    LogRecord startRecord = findStartRecord(recordList); 
    if(startRecord instanceof NullLogRecord) { 
     return new NullLogProcess(); 
    }  

    List<LogRecord> startEndRecord = findStartEndRecord(startRecord, recordList); 
    startRecord = startEndRecord.get(0); 
    endRecord = startEndRecord.get(1); 

    LogProcess process = returnLogProcess(startRecord, endRecord); 
    process.setLevel(level); 
    process.setChildren(findChildProcess(recordList, startRecord, endRecord, level + 1)); 

    return process; 
} 

private List<LogProcess> findChildProcess(List<LogRecord> recordList, LogRecord startRecord, LogRecord endRecord, int level) { 
    int fromIndex = recordList.indexOf(startRecord) + 1; 
    int toIndex = recordList.indexOf(endRecord); 
    if(toIndex > fromIndex) { 
     List<LogRecord> recordSubList = recordList.subList(fromIndex, toIndex); 
     return parse(recordSubList, level); 
    } else { 
     return new ArrayList<LogProcess>(); 
    } 
} 

private List<LogRecord> findStartEndRecord(LogRecord startRecord, List<LogRecord> recordList) { 
    List<LogRecord> startEndRecord = new ArrayList<LogRecord>(); 
    if (!recordList.isEmpty()) { 
     startEndRecord.add(startRecord); 
     for (LogRecord record : recordList) { 

      boolean isStartRecord = record.isStartPoint() && record.hasSameActionName(startRecord); 
      if(isStartRecord){ 
       startEndRecord = new ArrayList<LogRecord>();; 
       startEndRecord.add(record); 
       continue; 
      } 

      boolean isEndRecord = record.isEndPoint() && record.hasSameActionName(startRecord); 
      if (isEndRecord) { 
       startEndRecord.add(record); 
       return startEndRecord; 
      } 

     } 
     return startEndRecord; 
    } 
    return startEndRecord; 
} 

private LogRecord findStartRecord(List<LogRecord> recordList) { 
    for (LogRecord record : recordList) { 
     if (record.isStartPoint()){ 
      recordList.remove(record); 
      return record; 
     } 
    } 
    return new NullLogRecord(); 
} 

在for循環我只是得到第一個項目的結果,之後我得到了與標題相同的錯誤。請幫我解釋一下這個案例。

+0

是這是一個單線程還是多線程應用程序?請給出例外的StackTrace。 –

+0

這裏的錯誤:processList = parse(item,DEFAULT_START_LEVEL); –

+0

此刻的我是嘗試使用的ListIterator –

回答

2

此異常的名稱有點令人困惑,因爲它與多線程無關。

會發生什麼情況是您正在迭代正在迭代的正在修改的集合。

如果性能不是您最關心的問題,那麼簡單的出路就是複製列表並遍歷該副本並將項目添加到原始列表中。

+0

這也是我的想法,但我在代碼中找不到。 –

+0

你可以發佈整個堆棧跟蹤嗎?在引發ConcurrentModEx的時候,你知道它已經完成了哪一行代碼,然後你可以看到你的哪個java結構在那裏被使用。 – pveentjer

+0

雖然名稱很混亂,但它可能與多線程相關,因爲當另一個線程修改您重複使用的集合時,異常也會發生。 – zapl

0

我的猜測是它涉及到recordList.subList()

返回此列表的部分視圖。 [..]返回的列表由此列表支持。 [..]如果支持列表(即,此列表)在結構上以非返回列表以外的其他方式進行了修改,則此方法返回的列表的語義變得未定義。 [..]所有方法首先檢查後臺列表的實際modCount是否等於其預期值,如果不是,則拋出一個ConcurrentModificationException

我沒有看到任何修改,所以它可能發生在findProcess()。考慮創建一個列表的副本:

new ArrayList(recordList.subList()) 
+0

感謝馬庫斯,我會檢查這一點。 –

0

你得到,因爲這種異常:

for (LogRecord record : recordList) { 
     if (record.isStartPoint()){ 
      recordList.remove(record); <--- This is the cause 
      return record; 
     } 
} 

使用一個迭代器,而非

Iterator<LogRecord> iterator = recordList.iterator(); 
while(iterator.hasNext()){ 
    LogRecord logRecord = iterator.next(); 
    if(record.isStartPoint()){ 
     iterator.remove(); 
     return logRecord; 
    } 

檢查,如果這個工程

+0

我試試這個。但仍然是同樣的錯誤 –