Java中的ConcurrentModificationException是一个运行时异常(RuntimeException),表示在迭代一个集合(如List、Set、Map等)时,发生了并发修改操作。
当一个集合正在被迭代器遍历时,如果在遍历过程中对这个集合进行修改(如增删元素),就会导致ConcurrentModificationException异常的抛出。此异常通常发生在多线程环境下,因为多线程环境下,多个线程可以同时对一个集合进行修改操作。
下面通过两个示例说明ConcurrentModificationException异常的发生情况:
示例1:
List<String> strList = new ArrayList<>();
strList.add("AA");
strList.add("BB");
strList.add("CC");
for (String str : strList) {
if (str.equals("BB")) {
strList.remove(str);
}
}
以上代码实现了一个简单的List遍历与删除操作。在遍历过程中,如果遇到”BB”则删除该元素。但是这段代码会抛出ConcurrentModificationException异常,原因是在遍历的同时,又执行了删除操作,导致了集合的并发修改。
示例2:
Map<String, String> map = new HashMap<>();
map.put("A", "AA");
map.put("B", "BB");
for (String key : map.keySet()) {
if (key.equals("A")) {
map.put("C", "CC");
}
}
以上代码实现了一个Map遍历与添加操作。在遍历过程中,如果遇到”A”则添加一个新元素。但是这段代码同样会抛出ConcurrentModificationException异常,原因是在遍历的同时,又执行了添加操作,导致了集合的并发修改。
为了解决这个异常问题,我们可以采用以下方式:
- 在迭代器遍历集合时,不要直接对集合进行修改,可以通过迭代器提供的remove方法进行删除操作。如替换示例1的for循环:
Iterator<String> iterator = strList.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
if (str.equals("BB")) {
iterator.remove();
}
}
-
使用线程安全的集合类进行操作,如Vector、ConcurrentLinkedQueue等,或者使用Collections工具类提供的synchronizedCollection方法对非线程安全的集合进行包装。
-
将遍历与修改操作放在同一线程内完成,避免多线程同时对同一集合进行操作。
以上三种方式都可以避免ConcurrentModificationException异常的发生。