【问题标题】:Concurrent modification error when adding elements to LinkedList向LinkedList添加元素时并发修改错误
【发布时间】:2012-04-13 02:51:58
【问题描述】:

我有一个 LinkedList 对象列表。

    List<LinkedList<File1>> backup = new ArrayList<LinkedList<File1>>();

LinkedList 包含一些元素。我需要通过单击按钮动态添加其他元素。执行此操作时,我遇到了并发修改错误。我真的不明白为什么会弹出这个错误。代码如下:

private void jButton5ActionPerformed(java.awt.event.ActionEvent evt)      
{                                         
    // When JOIN button is clicked
    int parent_node,dist_node;
    // List<File1> temp_list = new ArrayList<File1>();
    File1 f_new = new File1();
    parent_node = Integer.parseInt(jTextField4.getText());
    dist_node = Integer.parseInt(jTextField5.getText());
    LinkedList<File1> tmp_bk = backup.get(parent_node);
    System.out.println("parent node : " + parent_node);
    System.out.println("dist node : " + dist_node);
    System.out.println("no of lists : " + backup.size());
    f_new.nod = backup.size();
    f_new.dist = dist_node;
    // temp_list.add(f_new);
    tmp_bk.add(f_new);

    ListIterator itr = it_bk.get(parent_node);
    while(itr.hasNext())
    {
        File1 f = (File1)itr.next();
        System.out.println("NODE : " + f.nod + "DIST : " + f.dist);
    }

}     

【问题讨论】:

  • 我还有一个迭代器数组列表,它指向每个链表。

标签: java


【解决方案1】:

这可能是因为您正在编辑列表,然后尝试使用原始迭代器。集合 API doesn't allow that。您需要在编辑列表后创建新的迭代器。

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

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

【讨论】:

  • @Divyashree 请接受答案.. 这可以帮助您获得更多帮助
【解决方案2】:

首先,如果你真的希望人们关注你的问题,你应该帮助他们用标准的英语清楚地提出问题。

其次,您应该指出您在代码中的确切位置收到 ConcurrentModificationError。

最后,什么是it_bk?它只是显示在您的代码中,没有任何解释。如果它是 ListIterators 的 ArrayList,那么它的 parent_node-th 元素肯定可能处于不确定 hasNext() 或 next() 是否安全的状态。我猜你用 tmp_bk.add(f_new); 修改了基础集合,所以一个预先存在的迭代器担心它的不变量可能会被违反。

一般建议:不要创建和保留迭代器(或它们的集合)。当你想要一个迭代器时,创建它,使用它,然后放弃它。

【讨论】:

  • 你很抱歉 :) 谢谢你的回复 :)
【解决方案3】:

JDK 1.5 中的 java.lang.Colletions 未同步。在早期版本(jdk 1.4),你不会发现这个问题。

对于这些问题有多种解决方案,您需要根据您的用例明智地选择其中一种。

  • 解决方案 1:可以使用 list.toArray() 将列表转换为数组并在数组上进行迭代。如果列表很大,不建议使用此方法。

  • 答案 2:通过将代码包装在同步块中,可以在迭代时锁定整个列表。如果应用程序高度并发,这种方法会对应用程序的可扩展性产生不利影响。

  • 答案 3:JDK 1.5 为您提供了 ConcurrentHashMap 和 CopyOnWriteArrayList 类,它们提供了更好的可伸缩性,并且 ConcurrentHashMap.iterator() 返回的迭代器在保持线程安全的同时不会抛出 ConcurrentModificationException。

  • 答案 4:通过引用基础集合“myStr”的迭代器“it”删除当前对象。 Iterator 对象为此提供了 it.remove() 方法。

【讨论】:

  • 非常感谢 :) 你的帖子很有帮助 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-29
相关资源
最近更新 更多