Skip to content

Commit 174194e

Browse files
authored
Merge pull request giantray#72 from AcceptedBoy/master
【add】iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re.md
2 parents 8fffae4 + 8561923 commit 174194e

1 file changed

+69
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
## 遍历集合时移除元素,怎样避免ConcurrentModificationException异常抛出
2+
3+
#### 问题:
4+
5+
在遍历集合的过程中,不会总出现`ConcurrentModificationException`异常的抛出,但是在下面的代码块中:
6+
7+
```java
8+
public static void main(String[] args) {
9+
Collection<Integer> l = new ArrayList<Integer>();
10+
11+
for (int i=0; i < 10; ++i) {
12+
l.add(new Integer(4));
13+
l.add(new Integer(5));
14+
l.add(new Integer(6));
15+
}
16+
17+
//遍历的过程中移除部分集合元素
18+
for (Integer i : l) {
19+
if (i.intValue() == 5) {
20+
l.remove(i);
21+
}
22+
}
23+
24+
System.out.println(l);
25+
}
26+
```
27+
28+
运行之后,结果显而易见,总是会抛出异常:
29+
30+
```java
31+
Exception in thread "main" java.util.ConcurrentModificationException
32+
```
33+
34+
所以,遍历集合时移除元素,怎样避免ConcurrentModificationException异常的产生?有什么好的解决办法?
35+
36+
#### 回答:
37+
38+
`Iterator.remove()`是线程安全的,所以你的代码可以这样写:
39+
40+
```java
41+
List<String> list = new ArrayList<>();
42+
43+
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
44+
String string = iterator.next();
45+
if (string.isEmpty()) {
46+
47+
// 从迭代器中移除集合元素,集合中相应的集合元素也会安全地被移除
48+
// 在这里,如果继续调用的是list.remove(string),那么仍会抛出异常
49+
iterator.remove();
50+
}
51+
}
52+
```
53+
54+
在遍历集合时修改集合的结构或内容的情况中,`Iterator.remove()`是唯一线程安全的方法。
55+
56+
#### 问题原因:
57+
58+
fail-fast, 快速失败机制,是java集合类的一种错误检查机制。当有多个线程同时对集合进行遍历以及内容或者结构的修改时,就有可能产生fail-fast机制。这意味着,当它们发现容器在迭代的过程中被修改时,就会抛出一个ConcurrentModificationException异常。
59+
60+
迭代器的快速失败行为无法得到保证,它不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,这个异常仅用于检测bug。这种迭代器并不是完备的处理机制,而只是作为并发问题的一个预警指示器。
61+
62+
63+
#### 拓展阅读:
64+
65+
[fail-fast机制的原理解析](https://github.com/AcceptedBoy/backstage-vacation-plan/blob/master/chapter1/concurrency/fail-fast.md)
66+
67+
#### StackOverFlow地址:
68+
69+
[http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re](http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re)

0 commit comments

Comments
 (0)