|
| 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