【问题标题】:ConcurrentModificationException with recursive use of Maps in Java在 Java 中递归使用 Maps 的 ConcurrentModificationException
【发布时间】:2013-05-20 11:32:36
【问题描述】:

我们正在创建一个由 JADE Agent 结构中的 AID 组成的树形结构。我们选择递归执行,这样无论系统中当前有多少代理程序,代码都可以执行,树结构可以动态更改以适应系统中当前代理程序的数量。我不确定是否需要设置某种锁以确保在不破坏结构完整性的情况下读取和写入 Map 对象。

这是导致问题的代码。

// BuildHierarchy method used to create the hierarchy based on Monitor Agents in the system
private void BuildHierarchy(Map<AID, Double>freqList, ArrayList<AID> childless, DefaultMutableTreeNode node){
    int i = 0;
    //creates an iterator for the freqList
    Iterator iter = freqList.entrySet().iterator();

    while(iter.hasNext()&& i < 2){

        Map.Entry pairs = (Map.Entry)iter.next();   
        //if (i<2){ 
            setParentNode((AID)pairs.getKey(), node);
        //}
        freqList.remove(pairs.getKey());
        i++;
    }
    BuildHierarchy(freqList, childless, node.getNextNode());
    BuildHierarchy(freqList, childless, node.getNextNode().getNextSibling());

}

【问题讨论】:

    标签: java recursion map concurrency agent


    【解决方案1】:

    当在已实现的集合上创建迭代器时,会在其上创建一个支持集,并且有一个计数器用于跟踪已实现的集合大小。在迭代期间,如果修改了集合,请说“freqList.remove(pairs.getKey());”然后它将删除元素并减小集合的大小,现在当下次迭代器对其调用 next() 操作时,它会从计数器实例中检测到集合已被修改并抛出 ConcurrentModificationException 。以下 HashIterator 类的代码将使您清楚地了解它是如何工作的

         final Entry<K,V> nextEntry() {
          if (modCount != expectedModCount)
                 throw new ConcurrentModificationException();
             Entry<K,V> e = next;
             if (e == null)
                throw new NoSuchElementException();
    
             if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                     ;
             }
            current = e;
            return e;
         }
    

    如果使用实际集合删除条目,则 modcount !=expectedCount 将为 true 并且会引发异常。

    【讨论】:

      【解决方案2】:

      您不能在迭代时修改Set(或底层Map),除非通过迭代器自己的remove 操作,否则将抛出ConcurrentModificationException。试试

      iter.remove();
      

      而不是

      freqList.remove(pairs.getKey());
      

      【讨论】:

        猜你喜欢
        • 2018-03-10
        • 1970-01-01
        • 2012-01-01
        • 1970-01-01
        • 2014-05-14
        • 2020-11-18
        • 1970-01-01
        • 1970-01-01
        • 2015-12-11
        相关资源
        最近更新 更多