在调试器中运行时引发ConcurrentModificationException

时间:2018-12-03 15:20:57

标签: java java.util.concurrent

我有以下出于某种原因抛出ConcurrentModificationException的代码。当我在带有线程之一的断点的调试器中运行它时抛出该异常,但显然不是这样。通过将断点(使用IntelliJ)设置为在线程级别挂起并检查每个类实例是否属于唯一线程,我已经确认该类不在线程之间共享。

public class EventAccumulator implements Observer {
  private AtomicInteger inputCount = new AtomicInteger();

  private ArrayDeque<Integer> countsList;

  ...

  private void updatePeriodCount() {
    countsList.addFirst(inputCount.get());
    inputCount.set(0);
    while (countsList.size() >= 30) {
      countsList.pollLast();
    }
    int finalCount = 0;
    for (int count : countsList) { //<--ConcurrentModificationException
      finalCount += count;
    }
    ...
  }

例外:

Exception in thread "Thread-23" java.util.ConcurrentModificationException
    at java.util.ArrayDeque$DeqIterator.next(ArrayDeque.java:648)
    at com.abc.dept.featurex.aspectx.a.EventAccumulator.updatePeriodCount(EventAccumulator.java:64)
    at com.abc.dept.featurex.aspectx.a.EventAccumulator.access$300(EventAccumulator.java:20)
    at com.abc.dept.featurex.aspectx.a.EventAccumulator$EventAccumulatorMaintenanceThread.run(EventAccumulator.java:99)

如果没有在线程之间共享类实例,为什么会抛出ConcurrentModificationException?假设调试模式使用的是IDE中未报告的后台线程(即通过某种优化),那么在非调试模式(即生产环境)中使用这种方法是否安全?

1 个答案:

答案 0 :(得分:0)

不,该类别几乎肯定不能在生产中使用。 调试器通常不会更改集合的内容。这就是这里发生的事情。在您遍历countsList时,其内容已更改。

尝试使用调试器或日志查找修改的源。也许您想在ArrayDequeue的某些方法中设置断点或重写断点并在其中放置一些日志。