ConcurrentModificationException
是 Java 中常见的运行时异常之一,通常在不当修改集合(如 List、Set 或 Map)时抛出。这种错误特别容易在多线程环境下出现,但单线程程序也可能触发它。
如何产生
- 单线程环境:当一个方法检测到正在进行的迭代与预期的结构不符时,会抛出此异常。例如,在使用迭代器遍历集合的同时,直接通过集合的方法(如
add()
、remove()
等)修改该集合,而不是使用迭代器自己的方法来修改集合,就会导致这个异常。 - 多线程环境:如果一个线程正在迭代一个集合,而另一个线程试图修改这个集合(添加、删除元素等),也会抛出
ConcurrentModificationException
异常。这是因为默认情况下大多数集合类(如ArrayList
、HashMap
等)都不是线程安全的,它们没有对并发修改进行同步处理。
示例代码(单线程)
import java.util.*;
public class Test {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for (Integer i : list) { // 使用迭代器隐式遍历
if (i == 2) {
list.remove(i); // 这里会抛出 ConcurrentModificationException
}
}
}
}
解决方案
- 使用迭代器的 remove 方法:在需要修改集合的地方,应该使用迭代器本身的
remove()
方法。
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
Integer i = it.next();
if(i == 2){
it.remove(); // 正确的方式
}
}
- 使用并发集合类:对于多线程环境,可以使用线程安全的集合类,比如
CopyOnWriteArrayList
、ConcurrentHashMap
等。 - 手动同步:也可以通过对集合进行显式的同步控制来避免这个问题,但是这种方式比较繁琐且容易出错。
理解并正确处理 ConcurrentModificationException
对于编写高效且无误的Java应用程序至关重要。无论是通过选择合适的集合类型还是合理设计代码逻辑,都是解决这一问题的有效手段。
THE END