在Java编程中,java.util.ConcurrentModificationException异常通常出现在多线程环境中或在单线程环境下对集合进行修改时。它表示当某个集合被一个线程遍历时,另一个线程修改了该集合,导致遍历时的状态和实际状态不一致,从而抛出该异常。

异常原因

ConcurrentModificationException最常见的发生场景是使用ArrayListHashMap等集合类的Iterator进行遍历时。如果在遍历的过程中,对集合进行了结构上的修改,例如添加或删除元素,就会抛出该异常。例如:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ConcurrentModificationExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        // 使用Iterator遍历集合
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
            // 在遍历过程中对集合进行修改
            if ("B".equals(element)) {
                list.remove(element); // 会抛出ConcurrentModificationException
            }
        }
    }
}

上面的代码在遍历集合时尝试删除元素"B",这将导致抛出ConcurrentModificationException

解决方案

为了避免这种异常,我们有几种解决方法:

  1. 使用Iterator的remove方法: Iterator接口提供了一个remove方法,可以安全地在遍历时删除当前元素。

```java import java.util.ArrayList; import java.util.Iterator; import java.util.List;

public class SafeRemovalExample { public static void main(String[] args) { List list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C");

       Iterator<String> iterator = list.iterator();
       while (iterator.hasNext()) {
           String element = iterator.next();
           System.out.println(element);
           if ("B".equals(element)) {
               iterator.remove(); // 使用Iterator的remove方法安全删除
           }
       }
       System.out.println("修改后的列表: " + list);
   }

} ```

  1. 使用CopyOnWriteArrayList: 在多线程环境下,可以使用CopyOnWriteArrayList,它是一个线程安全的集合,适合在多线程中读取数据的场景,而写入数据相对较少的情况下。

```java import java.util.List; import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafeExample { public static void main(String[] args) { List list = new CopyOnWriteArrayList<>(); list.add("A"); list.add("B"); list.add("C");

       // 创建一个线程用于修改列表
       new Thread(() -> {
           for (int i = 0; i < 5; i++) {
               list.add("D" + i);
           }
       }).start();

       // 遍历集合
       for (String element : list) {
           System.out.println(element);
           try {
               Thread.sleep(100); // 模拟遍历过程中的时间消耗
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }

} ```

  1. 使用Collections.synchronizedList方法: 可以将普通的列表变成线程安全的列表。

```java import java.util.Collections; import java.util.List; import java.util.ArrayList;

public class SynchronizedListExample { public static void main(String[] args) { List list = Collections.synchronizedList(new ArrayList<>()); list.add("A"); list.add("B"); list.add("C");

       synchronized (list) {
           for (String element : list) {
               System.out.println(element);
               list.remove(element); // 需要在同步块中移除元素
           }
       }
   }

} ```

总结

ConcurrentModificationException是Java中一个常见且重要的异常,它提醒我们在遍历集合时需要避免修改集合的数据结构。通过使用Iteratorremove方法、使用线程安全的集合类(如CopyOnWriteArrayList)或者通过synchronized同步进行操作,可以有效地规避该异常,保证代码的健壮性和稳定性。希望本文能帮助你更好地理解和处理ConcurrentModificationException异常。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部