【问题标题】:I keep getting java.util.concurrentmodificationexception.. How to fix this?我不断收到 java.util.concurrentmodificationexception .. 如何解决这个问题?
【发布时间】:2012-01-03 16:29:26
【问题描述】:

我一直在研究这个 sn-p 代码。这是我想要发生的伪代码:

a.检查节(这是一个列表)大小是否为 0。
b.如果section size为0,则通过调用sections.add(newSection)
自动将学生注册到该section c.else 如果节大小不为零,请检查是否与调度冲突
d.如果没有冲突,则通过调用sections.add(newSection)
将学生注册到该部分 e.else什么都不做

Java 不断向我抛出“java.util.concurrentmodificationexception”错误。我知道,我不应该在遍历列表时更改 ArrayList 的大小,因为它会修改迭代器。还有其他方法可以解决这个问题吗? :D

非常感谢。 非常感谢您的帮助。 :)

 public String enrollsTo(Section newSection){


        StringBuffer result = new StringBuffer();

        String resultNegative = "Failed to enroll in this section.";
        String resultPositive = "Successfully enrolled in section: " + newSection.getSectionName() + ".";

        int previousSectionSize = sections.size();

        if(this.sections.isEmpty()){
            this.sections.add(newSection);
            result.append(resultPositive);
        }else{
            for(Iterator<Section> iterator = sections.iterator(); iterator.hasNext() ; ){
                Section thisSection = iterator.next();

                if(thisSection.conflictsDayWith(newSection)==false &&
                    thisSection.conflictsTimeWith(newSection)==false){
                    this.sections.add(newSection);  //<-- i believe the problem lies here.
                    result.append(resultPositive);
                }
            }
        }
//      if(this.sections.size() == previousSectionSize){
//          result.append(resultNegative);
//      }
        return result.toString();
    }

【问题讨论】:

  • 注意:你的逻辑是错误的。而不是“如果没有冲突”,您正在测试“为每个不冲突的部分添加一个新部分”。
  • hmm..所以这就是为什么它看起来有点错误和奇怪。您必须指出,必须以某种方式对其进行改进,感谢您指出。 :D

标签: java concurrentmodification


【解决方案1】:

不要在 for 循环中使用 sections.add(newSection),因为这是对您当前正在迭代的集合的修改。

另外,您不想在决定是否添加newSection 之前检查所有部分吗?也许是这样的:

boolean conflict = false;
for (...) {
  if (/* check for conflict */) {
    conflict = true;
    break;
  }
}
if (!conflict) {
  sections.add(newSection);
}

【讨论】:

    【解决方案2】:

    来自ConcurrentModificationException 的javadoc(我的重点):

    检测到并发的方法可能会抛出此异常 在不允许修改时修改对象。

    例如一般不允许一个线程修改 一个集合,而另一个线程正在对其进行迭代。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器的实现(包括所有通用的 JRE 提供的目的集合实现)可以选择 如果检测到此行为,则抛出此异常。做的迭代器 这被称为快速失败迭代器,因为它们快速失败并且 干净利落,而不是冒着随意的、非确定性的行为的风险 未来的不确定时间。

    请注意,此异常并不总是表明对象具有 被不同的线程同时修改。如果单线程 发出一系列违反合同约定的方法调用 一个对象,该对象可能会抛出这个异常。 例如,如果一个 线程在迭代集合时直接修改集合 带有快速失败迭代器的集合,迭代器将抛出这个 例外。

    请注意,通常无法保证快速失败的行为 说,不可能在存在的情况下做出任何硬性保证 不同步的并发修改。快速失败的操作抛出 ConcurrentModificationException 尽最大努力。因此,它 编写一个依赖此异常的程序是错误的 其正确性:仅应使用 ConcurrentModificationException 检测错误。

    潜在的解决方案:不要直接添加到您正在迭代的列表中,而是添加到一个临时列表中,然后在您完成迭代后,执行addAll()

    【讨论】:

      【解决方案3】:

      在迭代集合时,您不能修改它。 this.sections.add(newSection); 行抛出异常。您可能需要使用一些布尔标记来检查条件

      if(thisSection.conflictsDayWith(newSection)==false &&
                          thisSection.conflictsTimeWith(newSection)==false)
      

      在for循环之后,如果你的布尔标记为真,那么你可以写

       this.sections.add(newSection);  
                          result.append(resultPositive);
      

      【讨论】:

        【解决方案4】:

        你的假设是正确的,

         this.sections.add(newSection);  
        

        绝对是您问题的根源。

        最简单的解决方案:使用一个布尔值表示该部分的可用性。开始假设它可用。如果您的迭代器中存在任何冲突,请将其设置为 false。在迭代器之后,如果该部分可用,则添加该部分(布尔值 true)。

        【讨论】:

          【解决方案5】:

          ConcurrentModificationExceptions 经常发生在您在迭代集合的元素时修改集合。阅读this tutorial 了解更多详情和这个旧的SO 帖子Why does it.next() throw java.util.ConcurrentModificationException?

          【讨论】:

            【解决方案6】:

            我同意@sudocode 的观点,即您不想在每次找到不冲突的部分时都添加 newSection。我原以为当您在调试器中单步执行代码时,这会很明显。 ;)

            顺便说一句,另一种(更晦涩)没有标志的方法是

            CHECK: {
              for (...) {
                if (/* check for conflict */) 
                  break CHECK;
              }
            
              sections.add(newSection);
            }
            

            【讨论】:

              猜你喜欢
              • 2016-04-28
              • 2019-01-22
              • 1970-01-01
              • 2023-01-07
              • 2022-06-14
              • 1970-01-01
              • 2019-10-06
              • 2019-10-14
              • 2020-03-25
              相关资源
              最近更新 更多