Java Vector源码学习
Vector
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
一:自动扩容机制
The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.
-
初始化
底层为对象数组
protected Object[] elementData;
protected int elementCount; 元素个数
protected int capacityIncrement;增长个数
public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } public Vector(int initialCapacity) { this(initialCapacity, 0); } public Vector() { this(10); }
-
add
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
判断是否分配
private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
关键:capacityIncrement》0时,每次增长capacityIncrement个元素;
capacityIncrement《=0时,2倍扩增;
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
-
remove: 并不会调节底层数组的大小
public synchronized E remove(int index) { modCount++; if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); E oldValue = elementData(index); int numMoved = elementCount - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--elementCount] = null; // Let gc do its work return oldValue; }
clear实现
public synchronized void removeAllElements() { modCount++; // Let gc do its work for (int i = 0; i < elementCount; i++) elementData[i] = null; elementCount = 0; }
真正减少底层数组容量
public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); } }
二:线程安全
jdk1.0 Vector ,jdk1.2 ArrayList
Vector 将可变状态封装在对象内部,通过对象锁对所有访问可变状态的代码进行同步,使得在该对象上不会发生并发访问。
对比ArrayList可以发现,增删改查所有方法都加了synchronized
关键字。
public synchronized int size() {
return elementCount;
}
三: Fail-Fast 机制
Vector返回的Iterator也是fail-fast。
public synchronized Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
// Racy but within spec, since modifications are checked
// within or after synchronization in next/previous
return cursor != elementCount;
}
public E next() {
synchronized (Vector.this) {
checkForComodification();
int i = cursor;
if (i >= elementCount)
throw new NoSuchElementException();
cursor = i + 1;
return elementData(lastRet = i);
}
}
}
Vector创建了Iterator之后,进行增删操作,modCount变化。-》ConcurrentModificationException
四:总结
-
Vector的问题
1)过多的同步,每个方法都有synchronized;
2)复合操作,并不安全,需要额外加锁。
if(!vector.contains(e)){ vector.add(e); }
-
Vector vs ArrayList
-
ArrayList扩增方式为1.5倍。
Vector扩容方式可以自设每次加几个,或者默认2倍扩容。
-
Vector线程安全
ArrayList线程不安全
-
Vector 为jdk1.0版本,并不推荐;
不需要线程安全时,推荐选择ArrayList;
需要线程安全时,List list = Collections.synchronizedList(new ArrayList(...));
Collections.synchronizedList虽然在增删改查方法都有synchronized;但是有好处;
(1) Vector 同步方法加锁的是
this
对象,没办法控制锁定的对象。SynchronizedList
的同步,使用的是synchronized
代码块对mutex
对象加锁,这个mutex
对象还能够通过构造函数传进来,也就是说我们可以指定锁定的对象。(2)对于迭代需要加大锁,Iterator.remove()的小锁并不需要,额外开销;synchronizedList.iterator()没synchronized关键字,自己加大锁,Iterator.remove()没有锁;
// 对迭代过程加锁 synchronized (vector) { for (Integer i : vector) { } }
-
@梦工厂 2018.3.7