Java源码-ArrayList
ArrayList底层原理:
-
1.ArrayList初始化为一个空数组
-
2.ArrayList的Add操作不是线程安全的
-
3.ArrayList添加第一个元素时,数组的容量设置为10
-
4.当ArrayList数组超过当前容量时,扩容至1.5倍(遇到计算结果为小数的,向下取整),第一次扩容后,容量为15,第二次扩容至22...
-
5.ArrayList在第一次和扩容后都会对数组进行拷贝,调用Arrays.copyOf方法。
单线程与多线程对比:
1.单线程安全,多线程不安全
2.如何解决
-
1.用Vector代替ArrayList
关于vector
-
初始化容量为10
-
add操作加了synchronized关键字,线程安全
-
扩容时是扩充至2倍
-
加了排斥锁增加安全性,但是会造成阻塞,性能较差
-
2.用Collections.synchronized(new ArrayList<>())
源码解析:
ad因为Collections.synchronizedList封装后的list,list的所有操作方法都带锁关键字, 所以线程安全
-
3.CopyOnWriteArrayList
copyOnWrite思想:
-
Copy on write:通过写时复制保证线程安全,一种读写分离的思想。
-
写操作:添加元素时,不直接往当前容器添加,而是先拷贝一份数组,在新的数组中添加元素后,在将原容器的引用指向新的容器。因为数组时用volatile关键字修饰的,所以当array重新赋值后,其他线程可以立即知道(volatile的可见性)
-
读操作:读取数组时,读老的数组,不需要加锁。
-
读写分离:写操作是copy了一份新的数组进行写,读操作是读老的数组,所以是读写分离。
add的流程:
-
先定义了一个可重入锁 ReentrantLock
-
添加元素前,先获取锁lock.lock()
-
添加元素时,先拷贝当前数组 Arrays.copyOf
-
添加元素时,扩容+1(len + 1)
-
添加元素后,将数组引用指向新加了元素后的数组setArray(newElements)

浙公网安备 33010602011771号