
JAVA源码分析 Vector 和 ArrayList
源码分析 Vector 和 ArrayList
每次我们会被问到这个问题,我们都知道 Vector 是线程安全的,而 ArrayList是线程不安全的。今天想引申出几个问题。
Vector 和 ArrayList 还有什么不同
Vector 容器是如何实现线程安全的
如果在多线程环境下,有没有别的 List 容器推荐,分别使用在什么场景?
首先回答第一个问题 Vector和ArrayList还有什么不同?
上图我们可以看到,Vetor和ArrayList都继承自AbstractList,所以大体上对外提供的接口大致相同,只是内部实现不同,底层都是基于数组加上扩容机制实现,除线程安全外Vetor和ArrayList最大的不同就是扩容方式不同,我们先给出结论,Vector在扩容时是提高一倍容量,而ArrayList是50%。下面我们可以具体分析一下扩容的源码。
Vector
初始化方法
我们从add(Object o)入手
可以看到add方法是加了synchronized关键字,这就说明Vector的add()方法在同一时刻只有一个线程能获取到锁,一目了然,Vector是使用 synchronized 同步机制实现到线程安全,它的每一个对外提供的 api 上都加有 synchronized 关键字。
下面我们看一下 add(e, elementData, elementCount); 这个方法
其中 e代表添加的元素,elementData代表内部的数组,s当前的容量。注意elementData数组的长度和s不是相同的,比如 Vector初始化的时候, elementData的初始化长度是10,而s=0。上面我们可以看到,如果当前容量s = 内部数组的长度以后,就需要调用 grow() 方法获取一个新的 内部数组,扩容的逻辑就在 grow() 方法里面。
下面我们看一下 grow() 方法:
来了来了,核心扩容逻辑来了 newCapacoty(int minCapacity)
ArrayList
构造方法
我们也从 add(Object o) 入手
我们可以看到,上面的方法,除了 add(E e) 方法没有 synchronized 关键字,基本都相同。
下面我们看一下 newCapacity(int minCapacity) 这个方法
ArrayList 线程安全处理
3.1 Collections.synchronizedList(new ArrayList);
3.2 CopyOnWriteArrayList() 容器,基于 ReadWriteLock 锁实现
来源:InfoQ
