并发修改异常
我有一小段代码,它给了我并发修改异常。我无法理解为什么我不断收到它,即使我没有看到任何并发修改正在进行。
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<>();
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a);
if (it.hasNext())
String item = it.next();
System.out.println(s);
}
}
I have this little piece of code and it gives me the concurrent modification exception. I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<>();
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a);
if (it.hasNext())
String item = it.next();
System.out.println(s);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
为了避免 ConcurrentModificationException,您应该这样编写代码:
java.util.ListIterator 允许您在迭代期间修改列表,但不能在创建列表和使用列表之间修改列表。
To avoid the
ConcurrentModificationException
, you should write your code like this:A
java.util.ListIterator
allows you to modify a list during iteration, but not between creating it and using it.在创建迭代器和开始使用迭代器之间,您向要迭代的列表添加了参数。这是并发修改。
将元素添加到列表后创建迭代器:
Between creating the iterator and starting to use the iterator, you added arguments to the list that is to be iterated. This is a concurrent modification.
Create the iterator AFTER you've finished adding elements to the list:
来自 ConcurrentModificatoinException 的 JavaDoc:: “通常不允许一个线程修改集合,而另一个线程正在迭代它”。
它只是意味着,如果您仍然有一个打开的迭代器,则不允许您修改列表,因为迭代器循环将中断。尝试移动
ListIterator; it = s.listIterator();
直到 for 循环之后。From the JavaDoc: for ConcurrentModificatoinException: "it is not generally permssible for one thread to modify a Collection while another thread is iterating over it".
It simply means that if you still have an open iterator, you aren't allowed to modify the list because the iterator loop will break. Try moving
ListIterator<String> it = s.listIterator();
till after the for loop.修改基础列表后,您不能继续迭代迭代器。在这里,您在向
s
添加一些项目之前创建迭代器,然后继续对其执行hasNext()
和next()
添加后,导致ConcurrentModificationException
You are not allowed to continue iterating over an iterator after the underlying list is modified. Here you create the iterator before adding a few items to
s
, and then proceed to do ahasNext()
and anext()
on it after the additions, leading to theConcurrentModificationException
如果上述解决方案不能正常工作。您可以使用旧的 for 循环来迭代列表,同时添加新项目。 请参阅下面的示例:
If the above solutions doesn't work properly. You can use old for-loop for iterating a List at the same time adding new items. See the example below:
要理解这一点,让我们看一下 HashMap 实现的源代码:
其中包含 HashIterator,如下所示:
每次创建迭代器时:
以避免您可以:
这将允许您同时迭代并添加或删除元素,而不会引发异常
有关 CopyOnWriteArrayList 的详细信息
to understand this lets look at source of HashMap implementation:
which contains HashIterator as below:
every time you create a iterator:
to avoid this u can:
this will allow you to iterate and add or remove elements at the same time without rising an exception
More info on CopyOnWriteArrayList
ConcurrentModificationException在单线程环境和多线程环境中都可能出现。
主要问题是所有通用迭代器(如 ArrayList 中使用的迭代器)都是 FailFast 迭代器,当我们尝试修改一个列表(如果一个迭代器已经在迭代该列表)时,该迭代器会失败。
解决方案->如果需求需要这种情况,请使用 CopyOnWriteArrayList 而不是使用 ArrayList。
对于完整的演示,可以使用下面提到的代码。
我们只需要将实现从 CopyOnWriteArrayList 更改为 ArrayList 即可。
有关更多信息,请点击此链接,这可能会很有帮助 ConcurrentModificationException Java 文档
ConcurrentModificationException may arise in both single threaded environment and multi-threaded environment.
The main catch is that all the general purpose iterators (like the one used in ArrayList) are all FailFast iterators, which fails when we try to modify one list if one iterator is already iterating over it.
Solution - > Use CopyOnWriteArrayList if such scenario is needed by the requirement rather than using ArrayList.
For a complete demo for this, below mentioned code can be used.
We just need to change the implementation from CopyOnWriteArrayList to ArrayList.
For more inifo follow this link this may be helpful alot ConcurrentModificationException Java Docs
这不起作用:
这起作用了:
This didn't work:
This worked:
查看 oracle 文档 页面。
就您而言,您在创建迭代器后修改了集合,因此遇到了异常。
如果您按照 Stephen C 答案更改代码,你不会得到这个错误。
Have a look at oracle documentation page.
In your case, you have modified the collection after creating the iterator and hence you have encountered the exception.
If you change your code as per Stephen C answer, you won't get this error.