简体   繁体   English

将元素添加到LinkedList时发生并发修改错误

[英]Concurrent modification error when adding elements to LinkedList

I have an List of LinkedList objects. 我有一个LinkedList对象列表。

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

The LinkedList contains some elements. LinkedList包含一些元素。 I need to add additional elements dynamically by clicking a button. 我需要通过单击按钮动态添加其他元素。 While doing this, I'm getting a concurrent modification error. 在执行此操作时,出现并发修改错误。 I really don't understand why this error is popping up. 我真的不明白为什么会弹出此错误。 Here is the code: 这是代码:

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);
    }

}     

It's probably because you're editing the list, then trying to use the original iterators. 可能是因为您正在编辑列表,然后尝试使用原始的迭代器。 The collections API doesn't allow that . 集合API 不允许这样做 You need to create new iterators after editing the list. 编辑列表后,您需要创建新的迭代器。

For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. 例如,通常不允许一个线程修改Collection而另一个线程对其进行迭代。 In general, the results of the iteration are undefined under these circumstances. 通常,在这些情况下,迭代的结果是不确定的。 Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. 如果检测到此行为,则某些Iterator实现(包括JRE提供的所有通用集合实现的实现)可能会选择抛出此异常。 Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future. 执行此操作的迭代器称为快速失败迭代器,因为它们会快速干净地失败,而不是在未来的不确定时间内冒任意,不确定的行为的风险。

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. 请注意,此异常并不总是表示对象已被其他线程同时修改。 If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. 如果单个线程发出违反对象约定的方法调用序列,则该对象可能会抛出此异常。 For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception. 例如,如果线程在使用快速失败迭代器迭代集合时直接修改了集合,则迭代器将抛出此异常。

First, if you really expect people to give their attention to your question, you should do them the favor of asking it clearly and in standard English. 首先,如果您真的希望别人关注您的问题,则应该帮助他们以清晰的英语水平提问。

Second, you should provide an indication of exactly where in your code you're getting the ConcurrentModificationError. 其次,您应该提供一个指示,指出在代码中确切出现ConcurrentModificationError的位置。

Finally, what is it_bk ? 最后, it_bk什么 It just shows up in your code without any explanation. 它只是显示在您的代码中,没有任何解释。 If it is an ArrayList of ListIterators it is certainly possible that its parent_node-th element is in a state where it isn't sure that hasNext() or next() will be safe. 如果它是ListIterators的ArrayList,则肯定有可能其parent_node-th元素处于不确定hasNext()或next()是否安全的状态。 I'm guessing you modified the underlying collection with your tmp_bk.add(f_new); 我猜您是用tmp_bk.add(f_new);修改了基础集合 and so a pre-existing iterator is worried that its invariants may be violated. 因此,先前存在的迭代器担心它的不变量可能会受到侵犯。

General advice: Don't create and retain iterators (or collections of them). 一般建议:不要创建和保留迭代器(或迭代器的集合)。 When you want an Iterator, create it, use it, and abandon it. 当您需要迭代器时,请创建它,然后使用它并放弃它。

java.lang.Colletions from JDK 1.5 is not synchronized. JDK 1.5中的java.lang.Colletions不同步。 In earlier version(jdk 1.4), you wont find this problem. 在早期版本(jdk 1.4)中,您不会发现此问题。

There are multiple solutions available for these problem and you need to choose one of them wisely as per your use case. 对于这些问题,有多种解决方案可用,您需要根据用例明智地选择其中一种。

  • Solution 1: The list can be converted to an array with list.toArray() and iterate on the array. 解决方案1:可以使用list.toArray()将列表转换为数组,并在数组上进行迭代。 This approach is not recommended if the list is large. 如果列表很大,则不建议使用此方法。

  • Answer 2: The entire list can be locked while iterating by wrapping your code within a synchronized block. 答案2:通过将代码包装在同步块中,可以在迭代时锁定整个列表。 This approach adversely affects scalability of your application if it is highly concurrent. 如果应用程序是高度并发的,则此方法会对应用程序的可伸缩性产生不利影响。

  • Answer 3: JDK 1.5 gives you ConcurrentHashMap and CopyOnWriteArrayList classes, which provide much better scalability and the iterator returned by ConcurrentHashMap.iterator() will not throw ConcurrentModificationException while preserving thread-safety. 答案3:JDK 1.5为您提供了ConcurrentHashMap和CopyOnWriteArrayList类,它们提供了更好的可伸缩性,并且ConcurrentHashMap.iterator()返回的迭代器在保留线程安全性的同时不会引发ConcurrentModificationException。

  • Answer 4: Remove the current object via the Iterator “it” which has a reference to the underlying collection “myStr”. 答案4:通过迭代器“ it”删除当前对象,该迭代器具有对基础集合“ myStr”的引用。 The Iterator object provides it.remove() method for this purpose. 为此,Iterator对象提供了it.remove()方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM