1

我有一个 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);
    }

}     
4

3 回答 3

6

这可能是因为您正在编辑列表,然后尝试使用原始迭代器。集合 API不允许这样做。您需要在编辑列表后创建新的迭代器。

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

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

于 2012-04-13T02:55:54.017 回答
1

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

其次,您应该提供一个指示,说明您在代码中的确切位置获得了 ConcurrentModificationError。

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

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

于 2012-04-13T03:49:33.963 回答
0

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() 方法。

于 2012-04-13T04:12:58.130 回答