Java Vector源码学习

2018-03-07  本文已影响59人  梦工厂

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.

  1. 初始化

    底层为对象数组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);
        }
    
  2. 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);
    }
    
  3. 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


四:总结

  1. Vector的问题

    1)过多的同步,每个方法都有synchronized;

    2)复合操作,并不安全,需要额外加锁。

    if(!vector.contains(e)){
      vector.add(e);
    }
    
  2. Vector vs ArrayList

    1. ArrayList扩增方式为1.5倍。

      Vector扩容方式可以自设每次加几个,或者默认2倍扩容。

    2. Vector线程安全

      ArrayList线程不安全

    3. 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

上一篇下一篇

猜你喜欢

热点阅读