Java中的ConcurrentModificationException是什么?

  • Post category:Java

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异常,原因是在遍历的同时,又执行了添加操作,导致了集合的并发修改。

为了解决这个异常问题,我们可以采用以下方式:

  1. 在迭代器遍历集合时,不要直接对集合进行修改,可以通过迭代器提供的remove方法进行删除操作。如替换示例1的for循环:
Iterator<String> iterator = strList.iterator();
while (iterator.hasNext()) {
    String str = iterator.next();
    if (str.equals("BB")) {
        iterator.remove();
    }
}
  1. 使用线程安全的集合类进行操作,如Vector、ConcurrentLinkedQueue等,或者使用Collections工具类提供的synchronizedCollection方法对非线程安全的集合进行包装。

  2. 将遍历与修改操作放在同一线程内完成,避免多线程同时对同一集合进行操作。

以上三种方式都可以避免ConcurrentModificationException异常的发生。