Java同步容器_Vector

Java同步容器_Vector

Vector的API

synchronized boolean        add(E object)
             void           add(int location, E object)
synchronized boolean        addAll(Collection<? extends E> collection)
synchronized boolean        addAll(int location, Collection<? extends E> collection)
synchronized void           addElement(E object)
synchronized int            capacity()
             void           clear()
synchronized Object         clone()
             boolean        contains(Object object)
synchronized boolean        containsAll(Collection<?> collection)
synchronized void           copyInto(Object[] elements)
synchronized E              elementAt(int location)
             Enumeration<E> elements()
synchronized void           ensureCapacity(int minimumCapacity)
synchronized boolean        equals(Object object)
synchronized E              firstElement()
             E              get(int location)
synchronized int            hashCode()
synchronized int            indexOf(Object object, int location)
             int            indexOf(Object object)
synchronized void           insertElementAt(E object, int location)
synchronized boolean        isEmpty()
synchronized E              lastElement()
synchronized int            lastIndexOf(Object object, int location)
synchronized int            lastIndexOf(Object object)
synchronized E              remove(int location)
             boolean        remove(Object object)
synchronized boolean        removeAll(Collection<?> collection)
synchronized void           removeAllElements()
synchronized boolean        removeElement(Object object)
synchronized void           removeElementAt(int location)
synchronized boolean        retainAll(Collection<?> collection)
synchronized E              set(int location, E object)
synchronized void           setElementAt(E object, int location)
synchronized void           setSize(int length)
synchronized int            size()
synchronized List<E>        subList(int start, int end)
synchronized <T> T[]        toArray(T[] contents)
synchronized Object[]       toArray()
synchronized String         toString()
synchronized void           trimToSize()

可以看到Vector中很多方法都是同步的。。


Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement。

(01) elementData 是"Object[]类型的数组",它保存了添加到Vector中的元素。elementData是个动态数组,如果初始化Vector时,没指定动态数组的>大小,则使用默认大小10。随着Vector中元素的增加,Vector的容量也会动态增长,capacityIncrement是与容量增长相关的增长系数,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

(02) elementCount 是动态数组的实际大小。

(03) capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时,增加的大小都是capacityIncrement。


Vector的动态增长方式

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);
}

通过源码可以看到如何确定Vector如何确定新的容量

当capacityIncrement大于零时,oldCapacity + capacityIncrement;

capacityIncrement小于零时,oldCapacity + oldCapacity 


Vector作为同步容器在并发环境下的使用

vector容器保证线程安全性的方法就是把每个对外暴露的存取方法用synchronized关键字同步化,这样会带来两个问题:性能不能保证,复合操作的原子性不能保证。看代码:

package container;


import java.util.Vector;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-8-7
 * Time: 下午1:05
 * To change this template use File | Settings | File Templates.
 */
public class VectorTest {

    public static Object getLast(Vector vector) {
        int lastIndex = vector.size() - 1;
        return vector.get(lastIndex);
    }

    public static void deleteLast(Vector vector) {
        int lastIndex = vector.size() - 1;
        vector.remove(lastIndex);
    }

    public static void main(String args[]) {
        final Vector vector = new Vector();

        for (int n = 0; n < 100; n++) {
            vector.add("vector" + n);
        }

        Runnable task1 = new Runnable() {
            @Override
            public void run() {
                System.out.println(getLast(vector));
            }
        };

        Runnable task2 = new Runnable() {
            @Override
            public void run() {
                deleteLast(vector);
            }
        };

        Thread t1 = new Thread(task1);
        Thread t2 = new Thread(task2);

        t2.setName("thread-2");   //thread2删除最后一元素
        t2.start();

        t1.setName("thread-1");   //thread1得到最后一个元素
        t1.start();
    }
}

上面的代码,在多线程环境下是不安全的,虽然get和remove操作是同步的,但getLast和deleteLast不是原子操作,是一个复合操作。

如图所示,如果发生这样的执行顺序

Java同步容器_Vector_第1张图片

结果肯定不是我们所期望的。

如果客户端是一组复合操作,它就没法同步了,依然需要客户端做额外同步。所以要保证getLast和deleteLast这种复合操作的原子性

public static Object getLast0(Vector vector) {
    //保证原子操作的同步锁(持有容器的锁,但是降低了并发性)
    synchronized (vector) {
        int lastIndex = vector.size() - 1;
        return vector.get(lastIndex);
    }
}

public static void deleteLast0(Vector vector) {
    synchronized (vector) {
        int lastIndex = vector.size() - 1;
        vector.remove(lastIndex);
    }
}

=====END=====

你可能感兴趣的:(Java同步容器_Vector)