038:Vector集合源码深度解析
1 Arraylist的Remove方法原理分析
课程内容:
1.Vector集合底层源码分析
2.Vector集合与Arraylist区别
3.Arraylist的Remove方法原理
4.Arraylist fail-fast原理
5.CopyOnWriteArraylist原理
size() 数组中数据个数;
length() 数组长度,扩容能够支撑存放的位置
2 Arraylist的Remove方法源码分析
System.arraycopy方法参数
src:源数组; srcPos:源数组要复制的起始位置;
dest:目的数组; destPos:目的数组放置的起始位置;
length:复制的长度。
remove方法源码分析
public E remove(int index) {
// 检查下标位置是否越界
rangeCheck(index);
// 获取要删除的对象
E oldValue = get(index);
// 计算移动的位置
int numMoved = size - index - 1;
// 判断删除的数据不是最后一个,将删除数据后面的数据往前移动一位
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
// 如果numMoved为0的情况下,后面不需要往前移动,直接将最后一条数据赋值为null
elementData[--size]= null;// clear to let GC do its work
return null;
}
3 Arraylist集合底层fail-fast机制
Fail-Fast机制原理
Fail-Fast是Java集合框架为了解决集合中结构发生改变的时候,快速失败的机制。
public class Test004 {
// 定义一个全局的集合存放,高并发情况下存在线程安全问题
private List<String> strings = new ArrayList<String>();
public static void main(String[] args) {
new Test004().startRun();
}
public void startRun() {
new Thread(new ThreadOne()).start();
new Thread(new ThreadTwo()).start();
}
/**
* 打印数据
*/
private void print() {
strings.forEach(x -> System.out.println("string:" + x));
}
class ThreadOne implements Runnable {
@Override
public void run() {
// 存储数据
for (int i = 0; i < 3; i++) {
strings.add("i:" + i);
print();
}
}
}
class ThreadTwo implements Runnable {
@Override
public void run() {
for (int j = 3; j < 6; j++) {
strings.add("j:" + j);
print();
}
}
}
}
运行结果:
4 Arraylist集合中ModCount作用
modCount 在做添加和删除的时候+1
当两条线程在做打印的时候,第一个线程正好执行结束用临时变量存储modCount,另一个线程执行了modCount++,临时变量的值expectedModCount就不会等于modCount,抛出异常。
解决方法:new ArrayList()换成new CopyOnWriteArrayList()
运行结果:
5 CopyOnWriteArraylist原理
基本概述
- 实现了List接口
- 内部持有一个ReentrantLock lock = new ReentrantLock();
- 底层是用volatile transient声明的数组 array
- 读写分离,写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
实现原理
注意:CopyOnWriteArrayList的add方法效率非常低,每次添加数据的时候都会不断扩容。
使用场景:存储一些配置信息,如黑白名单,数据不经常变动,能够保证线程安全问题,读的时候效率高。
6 Vector集合与Arraylist区别
Vector 源码分析:
默认构造函数中对数组的扩容为长度是为10;(如果创建了集合,没有使用的话比较占用内存);
Vector集合实现add方法的时候有synchronized关键字修饰;
Vector集合默认数组扩容是增长一倍,可以自己指定扩容倍数 (使用构造函数传递);
Vector查询也加了锁,高并发情况不建议使用,效率低;
Arraylist与Vector集合
相同点:底层都是采用数组实现
不同点:
- Arraylist底层数组默认长度为0,第一次调用add方法才会初始化,Vector底层数组默认长度为10;
- Arraylist底层扩容增加原数组的50%,Vector扩容默认增加原数组的100%,可以使用capacityIncrement设置增长容量;
- Arraylist线程不安全,Vector线程安全,底层采用synchronized保证线程安全问题;