import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Auther: YongXuezhen
* @Date: 2019/5/13 16:51
* @Description: 多线程情况下集合类不安全的问题,add方法没有加锁
*/
public class ContainNotSafeDemo {
public static void main(String[] args) {
//List<String> list =new Vector<>();
//List<String> list =Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList<>();
for(int i = 1;i <= 300; i++){
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
},String.valueOf(i)).start();
}
//java.util.ConcurrentModificationException并发修改的异常
/**
* 1.故障现象
* java.util.CurrentModificationException
* 2.导致原因
* 并发争抢修改导致,参考花名册写名字
* 一个人正在写,另一个同学过来抢夺,导致数据不一致异常。并发修改异常
* 3.解决方案
* (1)new Vector<>();
* (2)Collections.synchronizedList(new ArrayList<>());
* (3)new CopyOnWriteArrayList<>();
* 4.优化建议(同样的错误不犯第2次)
*/
}
}
/**
* 写时复制
* CopyOnWrite容器即写时复制的容器,忘一个容器添加元素的时候,不直接往当前容器Object[]中添加,
* 而是先将当前容器Object[]进行copy,复制出一个新的容器Object[] newElements,然后往新的容器中
* 添加元素,添加完元素之后,再将原容器的引用指向新容器setArray(newElements);.这样做的好处是
* 可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素,所以CopyOnWrite
* 容器也是一种读写分离的思想,读和写不同的容器。
*
* 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();
* }
* }
*/