1、为什么要有CopyOnWriteArrayList
原因是ArrayList 在多线程的情况下 会有线程不安全的问题
/**
* 一、list 在多线程下是不安全的 会报 如下的异常,出现的情况是 当前的容器列表既有读又有写,如果只是写或者读不会报如下的异常。
* java.util.ConcurrentModificationException 这个叫并发修改异常
* 二、解决办法
* 1、List list = new Vector();这个是线程安全的
* 2、List list = Collections.synchronizedList(new ArrayList<>());
* 3、List list = new CopyOnWriteArrayList(); 叫写入时复制 简称cow,
* 三、CopyOnWriteArrayList的原理
* 就是写的时候先复制一份数据,在新的数据上写,写好了指针指向新的数据。就是读写分离的一个思想。
* 四、CopyOnWriteArrayList 的优点缺点
* 优点:
* 读操作性能很高,因为无需任何同步措施,比较适用于读多写少的并发场景。Java的list在遍历时,
* 若中途有别的线程对list容器进行修改,则会抛出ConcurrentModificationException异常。
* 而CopyOnWriteArrayList由于其"读写分离"的思想,遍历和修改操作分别作用在不同的list容器,
* 所以在使用迭代器进行遍历时候,也就不会抛出ConcurrentModificationException异常了
*
* 缺点:
* 缺点也很明显,一是内存占用问题,毕竟每次执行写操作都要将原容器拷贝一份,数据量大时,对内存压力较大,
* 可能会引起频繁GC;二是无法保证实时性,Vector对于读写操作均加锁同步,可以保证读和写的强一致性。
* 而CopyOnWriteArrayList由于其实现策略的原因,写和读分别作用在新老不同容器上,
* 在写操作执行过程中,读不会阻塞但读取到的却是老容器的数据。
*
*
*
*/
public class CopyOnWriteArrayListDemo {
public static void main(String[] args) {
//判断当前机器最大的处理器数 就是看看是几核的cpu
System.out.println(Runtime.getRuntime().availableProcessors());
int num = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor excutors = new ThreadPoolExecutor(
8,
num,
1000, //超时等待的时间,就是345 中的窗口 这段时间没有人办理业务就要关闭,释放线程了。
TimeUnit.SECONDS,
new LinkedBlockingQueue(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());//其中的一个拒绝策略,
//List list = new LinkedList();
//List list = new Vector();
//List list = Collections.synchronizedList(new ArrayList<>());
List list = new CopyOnWriteArrayList();
try{
for (int i = 0; i < 94; i++) {
excutors.execute(()->{
System.out.println(Thread.currentThread().getName()+"======ok");
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
excutors.shutdown();
}
}
}