java.util.concurrentModificationExection 并发修改异常
Posted on 2019-09-23 02:37 MrEven 阅读(265) 评论(0) 收藏 举报多线程环境下线程不安全的集合类
ArrayList、HashSet、 HashMap....
解决方案:
ArrayList多线程环境下导致并发修改异常的解决方法:
1、使用 new Vector<>(),因为Vector中的add()方法添加了synchronize的同步关键字,所以在多线程环境下可以解决并发修改异常,但会导致并发量下降。
2、使用Collections.synchronizeList(new ArrayList<>()),也可以解决并发修改异常
3、使用new CopyOnWriteArrayList<>(),写实复制的(读写分离的思想)
写时复制:
CopyOnWrite 容器即写时复制的容器,往一个容器添加元素的时候,不直接往当前的容器Object[]添加,而是先将当前的容器Object[]进行Copy,复制出一个新的容器Object[] newElements,然后往新的容器Object[] newElements 里面添加元素,添加完元素之后,再将原容器的引用指向新的容器setArray(newElements);这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前的容器不会添加任何元素。所以CopyOnWrite 容器也是 “一种读写分离的思想”,读和写不同的容器。
源码解析如下:
1 public boolean add(E e) { 2 final ReentrantLock lock = this.lock; 3 lock.lock(); 4 try { 5 Object[] elements = getArray(); 6 int len = elements.length;//获取原容器的长度(大小) 7 Object[] newElements = Arrays.copyOf(elements, len + 1);//复制一个新的Object 容器 8 newElements[len] = e;//往新的Object容器中添加元素 9 setArray(newElements);//将原容器的引用指向新容器 10 return true; 11 } finally { 12 lock.unlock(); 13 }
多线程环境下集合类不安全问题的小case,以及解决方法。
1 package com.company.array.demo; 2 3 import java.util.*; 4 import java.util.concurrent.ConcurrentHashMap; 5 import java.util.concurrent.CopyOnWriteArrayList; 6 import java.util.concurrent.CopyOnWriteArraySet; 7 8 /** 9 * 集合类不安全的问题 10 * ArrayList 11 * HashSet 12 * Map 13 *java.util.ConcurrentModificationException 常用集合类多线程下并发 14 *修改异常的解决方案。 15 */ 16 public class ContainerNotSafeDemo { 17 public static void main(String[] args) { 18 listNotSafe(); 19 setNotSafe(); 20 mapNotSafe(); 21 } 22 23 //解决HashMap多线程下面并发修改异常的方法 24 public static void mapNotSafe() { 25 /*Map<String, String> map = new HashMap<>();*/ //并发修改异常 26 /*Map<String, String> map = Collections.synchronizedMap(new HashMap<>());*//方案一 27 Map<String, String> map = new ConcurrentHashMap<>();//方案二 28 for (int i = 1; i <= 30; i++) { 29 new Thread(() -> { 30 map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8)); 31 System.out.println(map); 32 }, String.valueOf(i)).start(); 33 } 34 } 35 36 //解决HashSet多线程下面并发修改异常的方法 37 public static void setNotSafe() { 38 /*Set<String> set = new HashSet<>();*///多线程下线程不安全。并发修改异常 39 /*Set<String> set= Collections.synchronizedSet(new HashSet<>());*//方案一 40 Set<String> set = new CopyOnWriteArraySet<>();// 方案二 41 for (int i = 1; i <= 30; i++) { 42 new Thread(() -> { 43 set.add(UUID.randomUUID().toString().substring(0, 8)); 44 System.out.println(set); 45 }, String.valueOf(i)).start(); 46 } 47 } 48 49 //解决ArrayList多线程下面并发修改异常的方法 50 public static void listNotSafe() { 51 /*List<String> list1 = new Vector<>();*///方案一 52 /*List<String> list2 = Collections.synchronizedList(new ArrayList<>());*///方案二 53 List<String> list = new CopyOnWriteArrayList<>();//方案三 54 for (int i = 1; i <= 10; i++) { 55 new Thread(() -> { 56 list.add(UUID.randomUUID().toString().substring(0, 8)); 57 System.out.println(list); 58 }, String.valueOf(i)).start(); 59 } 60 } 61 }
人生本来就是一场漫长的旅行,我们无时无刻不在旅途的路上。
浙公网安备 33010602011771号