Java错误并发修改异常

时间:2014-01-12 14:35:26

标签: java concurrentmodification

我在下面的案例中需要帮助: 我有2种方法:

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

和第二种方法

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循环中的方法calculatime我得到第一个项目的结果,然后我得到错误相同的标题。请帮助我,并为此案例解释一下。

3 个答案:

答案 0 :(得分:2)

此异常的名称有点令人困惑,因为它与多线程无关。

当您在迭代它时正在迭代正在修改的集合时,会发生什么。

如果性能不是您最关心的问题,那么一个简单的方法就是复制列表并迭代该副本并将项目添加到原始列表中。

答案 1 :(得分:0)

我的猜测是与recordList.subList()

有关
  

返回此列表部分的视图。 [..]返回的列表由此列表支持。 [..]如果支持列表(即此列表)在结构上以除返回列表之外的任何方式进行修改,则此方法返回的列表的语义将变为未定义。 [..]所有方法首先检查后备列表的实际modCount是否等于其预期值,如果不是,则抛出 ConcurrentModificationException

我没有看到任何修改,因此它可能发生在findProcess()中。考虑创建该列表的副本:

new ArrayList(recordList.subList())

答案 2 :(得分: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;
   }

检查是否有效