解决集合类不安全
ArrayList,HashSet,hashMap等都是现成不安全的,会出现java.until.ConcurrentModificationException:并发修改异常
1)各类集合不安全解决方法:
1)List
List<String> list = new ArrayList<>();
==========解决办法==================
List<String> list = new Vector<>();
List<String> list = Collections.synchronizedList(new ArrayList<>());
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
2)Set
Set<String> set = new HashSet<>();
=================解决办法==============
Set<String> set = Collections.synchronizedSet(new HashSet<>());
Set<String> set = new CopyOnWriteArraySet<String>();
3)Map
Map<String, String> map = new HashMap<>();
===================解决办法==============
Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
Map<String, String> map = new Hashtable<>();
Map<String, String> map = new ConcurrentHashMap<>();
以下内容摘自:https://www.cnblogs.com/baizhanshi/p/7699811.html
2)CopyOnWrite容器介绍
- 什么是CopyOnWrite容器
CopyOnWrite容器即写时复制的容器,当往容器中添加元素时,不直接往当前容器中添加元素,而是先将当前容器进行copy,复制出一个新的容器,然后将元素添加至新容器中,在将原容器的引用指向新容器。
-
思想
1、读写分离,读和写分开 ,实现了多个线程并发的读,而不需要加锁,因为当前容器中不会添加任何元素,元素时添加到新容器中
2、最终一致性
3、使用另外开辟空间的思路,来解决并发冲突 -
CopyOnWriteArrayList的实现原理
添加元素:拷贝当前容器,将元素添加到新容器中。添加时上锁,避免多个线程写的时候会Copy出N个副本出来。
//CopyOnWriteArrayList的add源码
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
读取元素:读取时不需上锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的CopyOnWriteArrayList。
//CopyOnWriteArrayList的get源码
public E get(int index) {
return get(getArray(), index);
}
CopyOnWriteArrayList缺点:
1、由于写操作的时候,需要拷贝数组,会消耗内存,如果原数组的内容比较多的情况下,可能导致young gc或者full gc
2、不能用于实时读的场景,拷贝数组、新增元素都需要时间,当添加元素时,其他线程读取到数据可能还是旧的,虽然CopyOnWriteArrayList 能做到最终一致性,但是还是没法满足实时性要求;
CopyOnWriteArrayList 合适读多写少的场景
参考文档:
https://www.cnblogs.com/baizhanshi/p/7699811.html
更多文章请关注《万象专栏》
转载请注明出处:https://www.wanxiangsucai.com/read/cv9386