java-并发-同步容器

Java常用的容器有ArrayList、LinkedList、HashMap等等,这些容器都是非线程安全的。如果有多个线程并发地访问这些容器时,就会出现问题。在编写程序时,必须要求程序员手动地在任何访问到这些容器的地方进行同步处理。
所以,Java提供了同步容器供用户使用,Java库本身就有多种线程安全的容器和同步工具。
1)Vector、Stack、HashTable
Vector实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施。
Stack也是一个同步容器,它的方法也用synchronized进行了同步,它实际上是继承于Vector类。
HashTable实现了Map接口,它和HashMap很相似,但是HashTable进行了同步处理,而HashMap没有。
2)Collections类中提供的静态工厂方法创建的类
Collections类是一个工具提供类。在Collections类中提供了大量的方法,比如对集合或者容器进行排序、查找等操作。更重要的是,在它里面提供了几个静态工厂方法来创建同步容器类。JDK1.2中加入的同步包装类,这些类都是由Collections.synchronizedXXX工厂方法。同步容器都是线程安全的,但是对于复合操作,有些缺点。

① 迭代:在查觉到容器在迭代开始以后被修改,会抛出一个未检查异常ConcurrentModificationException,为了避免这个异常,需要在迭代期间,持有一个容器锁。但是锁的缺点也很明显,就是对性能的影响。
② 隐藏迭代器:StringBuilder的toString方法会通过迭代容器中的每个元素,另外容器的hashCode和equals方法也会间接地调用迭代。类似地,contailAll、removeAll、retainAll方法,以及容器作为参数的构造函数,都会对容器进行迭代。
③ 缺少即加入等一些复合操作

public static Object getLast(Vector list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
public static void deleteLast(Vector list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}

getLast和deleteLast都是复合操作,由先前对原子性的分析可以判断,这依然存在线程安全问题,有可能会抛出ArrayIndexOutOfBoundsException的异常。
解决办法就是通过对这些复合操作加锁,jdk1.5从同步容器的具体实现源码可知,同步容器中的方法采用了synchronized进行了同步,那么必然会影响到程序的执行性能。于是Java提供了性能更优并发容器。

Vector

Vector 是矢量队列,它是JDK1.0版本添加的类。
1、继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。
2、实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
3、Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。Vector不支持序列化,即没有实现java.io.Serializable接口。

Vector共有4个构造函数
// 默认构造函数
Vector()
// capacity是Vector的默认容量大小。当由于增加数据导致容量增加时,每次容量会增加一倍。
Vector(int capacity)
// capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
Vector(int capacity, int capacityIncrement)
// 创建一个包含collection的Vector
Vector(Collection<? extends E> collection)
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()

源码

package java.util;
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

    // 保存Vector中数据的数组
    protected Object[] elementData;
    // 实际数据的数量
    protected int elementCount;
    // 容量增长系数
    protected int capacityIncrement;
    // Vector的序列版本号
    private static final long serialVersionUID = -2767605614048989439L;
    // Vector构造函数。默认容量是10。
    public Vector() {
        this(10);
    }
    // 指定Vector容量大小的构造函数
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
    // 指定Vector"容量大小"和"增长系数"的构造函数
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        // 新建一个数组,数组容量是initialCapacity
        this.elementData = new Object[initialCapacity];
        // 设置容量增长系数
        this.capacityIncrement = capacityIncrement;
    }
    // 指定集合的Vector构造函数。
    public Vector(Collection<? extends E> c) {
        // 获取“集合(c)”的数组,并将其赋值给elementData
        elementData = c.toArray();
        // 设置数组长度
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }
    // 将数组Vector的全部元素都拷贝到数组anArray中
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }
    // 将当前容量值设为 =实际元素个数
    public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }
    // 确认“Vector容量”的帮助函数
    private void ensureCapacityHelper(int minCapacity) {
        int oldCapacity = elementData.length;
        // 当Vector的容量不足以容纳当前的全部元素,增加容量大小。
        // 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement
        // 否则,将容量增大一倍。
        if (minCapacity > oldCapacity) {
            Object[] oldData = elementData;
            int newCapacity = (capacityIncrement > 0) ?
                (oldCapacity + capacityIncrement) : (oldCapacity * 2);
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }
    // 确定Vector的容量。
    public synchronized void ensureCapacity(int minCapacity) {
        // 将Vector的改变统计数+1
        modCount++;
        ensureCapacityHelper(minCapacity);
    }
    // 设置容量值为 newSize
    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            // 若 "newSize 大于 Vector容量",则调整Vector的大小。
            ensureCapacityHelper(newSize);
        } else {
            // 若 "newSize 小于/等于 Vector容量",则将newSize位置开始的元素都设置为null
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }
    // 返回“Vector的总的容量”
    public synchronized int capacity() {
        return elementData.length;
    }
    // 返回“Vector的实际大小”,即Vector中元素个数
    public synchronized int size() {
        return elementCount;
    }
    // 判断Vector是否为空
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }
    // 返回“Vector中全部元素对应的Enumeration”
    public Enumeration<E> elements() {
        // 通过匿名类实现Enumeration
        return new Enumeration<E>() {
            int count = 0;
            // 是否存在下一个元素
            public boolean hasMoreElements() {
                return count < elementCount;
            }
            // 获取下一个元素
            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return (E)elementData[count++];
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }
    // 返回Vector中是否包含对象(o)
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }
    // 从index位置开始向后查找元素(o)。
    // 若找到,则返回元素的索引值;否则,返回-1
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            // 若查找元素为null,则正向找出null元素,并返回它对应的序号
            for (int i = index ; i < elementCount ; i++)
            if (elementData[i]==null)
                return i;
        } else {
            // 若查找元素不为null,则正向找出该元素,并返回它对应的序号
            for (int i = index ; i < elementCount ; i++)
            if (o.equals(elementData[i]))
                return i;
        }
        return -1;
    }
    // 查找并返回元素(o)在Vector中的索引值
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }
    // 从后向前查找元素(o)。并返回元素的索引
    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-1);
    }
    // 从后向前查找元素(o)。开始位置是从前向后的第index个数;
    // 若找到,则返回元素的“索引值”;否则,返回-1。
    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
        if (o == null) {
            // 若查找元素为null,则反向找出null元素,并返回它对应的序号
            for (int i = index; i >= 0; i--)
            if (elementData[i]==null)
                return i;
        } else {
            // 若查找元素不为null,则反向找出该元素,并返回它对应的序号
            for (int i = index; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
        }
        return -1;
    }
    // 返回Vector中index位置的元素。
    // 若index月结,则抛出异常
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }
        return (E)elementData[index];
    }
    // 获取Vector中的第一个元素。
    // 若失败,则抛出异常!
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return (E)elementData[0];
    }
    // 获取Vector中的最后一个元素。
    // 若失败,则抛出异常!
    public synchronized E lastElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return (E)elementData[elementCount - 1];
    }
    // 设置index位置的元素值为obj
    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                 elementCount);
        }
        elementData[index] = obj;
    }
    // 删除index位置的元素
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                 elementCount);
        } else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }
    // 在index位置处插入元素(obj)
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                 + " > " + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }
    // 将“元素obj”添加到Vector末尾
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
    // 在Vector中查找并删除元素obj。
    // 成功的话,返回true;否则,返回false。
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
    // 删除Vector中的全部元素
    public synchronized void removeAllElements() {
        modCount++;
        // 将Vector中的全部元素设为null
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;
        elementCount = 0;
    }
    // 克隆函数
    public synchronized Object clone() {
        try {
            Vector<E> v = (Vector<E>) super.clone();
            // 将当前Vector的全部元素拷贝到v中
            v.elementData = Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }
    // 返回Object数组
    public synchronized Object[] toArray() {
        return Arrays.copyOf(elementData, elementCount);
    }
    // 返回Vector的模板数组。所谓模板数组,即可以将T设为任意的数据类型
    public synchronized <T> T[] toArray(T[] a) {
        // 若数组a的大小 < Vector的元素个数;
        // 则新建一个T[]数组,数组大小是“Vector的元素个数”,并将“Vector”全部拷贝到新数组中
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());
        // 若数组a的大小 >= Vector的元素个数;
        // 则将Vector的全部元素都拷贝到数组a中。
    System.arraycopy(elementData, 0, a, 0, elementCount);
        if (a.length > elementCount)
            a[elementCount] = null;
        return a;
    }
    // 获取index位置的元素
    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        return (E)elementData[index];
    }
    // 设置index位置的值为element。并返回index位置的原始值
    public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        Object oldValue = elementData[index];
        elementData[index] = element;
        return (E)oldValue;
    }
    // 将“元素e”添加到Vector最后。
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    // 删除Vector中的元素o
    public boolean remove(Object o) {
        return removeElement(o);
    }
    // 在index位置添加元素element
    public void add(int index, E element) {
        insertElementAt(element, index);
    }
    // 删除index位置的元素,并返回index位置的原始值
    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        Object 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 (E)oldValue;
    }
    // 清空Vector
    public void clear() {
        removeAllElements();
    }
    // 返回Vector是否包含集合c
    public synchronized boolean containsAll(Collection<?> c) {
        return super.containsAll(c);
    }
    // 将集合c添加到Vector中
    public synchronized boolean addAll(Collection<? extends E> c) {
        modCount++;
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);
        // 将集合c的全部元素拷贝到数组elementData中
        System.arraycopy(a, 0, elementData, elementCount, numNew);
        elementCount += numNew;
        return numNew != 0;
    }
    // 删除集合c的全部元素
    public synchronized boolean removeAll(Collection<?> c) {
        return super.removeAll(c);
    }
    // 删除“非集合c中的元素”
    public synchronized boolean retainAll(Collection<?> c)  {
        return super.retainAll(c);
    }
    // 从index位置开始,将集合c添加到Vector中
    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        modCount++;
        if (index < 0 || index > elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);
        int numMoved = elementCount - index;
        if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
        System.arraycopy(a, 0, elementData, index, numNew);
        elementCount += numNew;
        return numNew != 0;
    }
    // 返回两个对象是否相等
    public synchronized boolean equals(Object o) {
        return super.equals(o);
    }
    // 计算哈希值
    public synchronized int hashCode() {
        return super.hashCode();
    }
    // 调用父类的toString()
    public synchronized String toString() {
        return super.toString();
    }
    // 获取Vector中fromIndex(包括)到toIndex(不包括)的子集
    public synchronized List<E> subList(int fromIndex, int toIndex) {
        return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
    }
    // 删除Vector中fromIndex到toIndex的元素
    protected synchronized void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = elementCount - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);
        // Let gc do its work
        int newElementCount = elementCount - (toIndex-fromIndex);
        while (elementCount != newElementCount)
            elementData[--elementCount] = null;
    }
    // java.io.Serializable的写入函数
    private synchronized void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        s.defaultWriteObject();
    }
}

Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10。
当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 >0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。Vector的克隆函数,即是将全部元素克隆到一个数组中。
4种遍历方式

import java.util.*;
/*
 * @desc Vector遍历方式和效率的测试程序。
 *
 * @author skywang
 */
public class VectorRandomAccessTest {
    public static void main(String[] args) {
        Vector vec= new Vector();
        for (int i=0; i<100000; i++)
            vec.add(i);
        iteratorThroughRandomAccess(vec) ;
        iteratorThroughIterator(vec) ;
        iteratorThroughFor2(vec) ;
        iteratorThroughEnumeration(vec) ;

    }
    private static void isRandomAccessSupported(List list) {
        if (list instanceof RandomAccess) {
            System.out.println("RandomAccess implemented!");
        } else {
            System.out.println("RandomAccess not implemented!");
        }
    }
    public static void iteratorThroughRandomAccess(List list) {
        long startTime;
        long endTime;
        startTime = System.currentTimeMillis();
        for (int i=0; i<list.size(); i++) {
            list.get(i);
        }
        endTime = System.currentTimeMillis();
        long interval = endTime - startTime;
        System.out.println("iteratorThroughRandomAccess:" + interval+" ms");
    }
    public static void iteratorThroughIterator(List list) {
        long startTime;
        long endTime;
        startTime = System.currentTimeMillis();
        for(Iterator iter = list.iterator(); iter.hasNext(); ) {
            iter.next();
        }
        endTime = System.currentTimeMillis();
        long interval = endTime - startTime;
        System.out.println("iteratorThroughIterator:" + interval+" ms");
    }
    public static void iteratorThroughFor2(List list) {
        long startTime;
        long endTime;
        startTime = System.currentTimeMillis();
        for(Object obj:list)

        endTime = System.currentTimeMillis();
        long interval = endTime - startTime;
        System.out.println("iteratorThroughFor2:" + interval+" ms");
    }
    public static void iteratorThroughEnumeration(Vector vec) {
        long startTime;
        long endTime;
        startTime = System.currentTimeMillis();
        for(Enumeration enu = vec.elements(); enu.hasMoreElements(); ) {
            enu.nextElement();
        }
        endTime = System.currentTimeMillis();
        long interval = endTime - startTime;
        System.out.println("iteratorThroughEnumeration:" + interval+" ms");
    }
}
运行结果:
iteratorThroughRandomAccess:6 ms
iteratorThroughIterator:9 ms
iteratorThroughFor2:8 ms
iteratorThroughEnumeration:7 ms
总结:遍历Vector,使用索引的随机访问方式最快,使用迭代器最慢。
import java.util.Vector;
import java.util.List;
import java.util.Iterator;
import java.util.Enumeration;

public class VectorTest {
    public static void main(String[] args) {
        // 新建Vector
        Vector vec = new Vector();

        // 添加元素
        vec.add("1");
        vec.add("2");
        vec.add("3");
        vec.add("4");
        vec.add("5");
        // 设置第一个元素为100
        vec.set(0, "100");
        // 将“500”插入到第3个位置
        vec.add(2, "300");
        System.out.println("vec:"+vec);
        // (顺序查找)获取100的索引
        System.out.println("vec.indexOf(100):"+vec.indexOf("100"));
        // (倒序查找)获取100的索引
        System.out.println("vec.lastIndexOf(100):"+vec.lastIndexOf("100"));
        // 获取第一个元素
        System.out.println("vec.firstElement():"+vec.firstElement());
        // 获取第3个元素
        System.out.println("vec.elementAt(2):"+vec.elementAt(2));
        // 获取最后一个元素
        System.out.println("vec.lastElement():"+vec.lastElement());
        // 获取Vector的大小
        System.out.println("size:"+vec.size());
        // 获取Vector的总的容量
        System.out.println("capacity:"+vec.capacity());
        // 获取vector的“第2”到“第4”个元素
        System.out.println("vec 2 to 4:"+vec.subList(1, 4));
        // 通过Enumeration遍历Vector
        Enumeration enu = vec.elements();
        while(enu.hasMoreElements())
            System.out.println("nextElement():"+enu.nextElement());

        Vector retainVec = new Vector();
        retainVec.add("100");
        retainVec.add("300");
        // 获取“vec”中包含在“retainVec中的元素”的集合
        System.out.println("vec.retain():"+vec.retainAll(retainVec));
        System.out.println("vec:"+vec);

        // 获取vec对应的String数组
        String[] arr = (String[]) vec.toArray(new String[0]);
        for (String str:arr)
            System.out.println("str:"+str);
        // 清空Vector。clear()和removeAllElements()一样!
        vec.clear();
//        vec.removeAllElements();
        // 判断Vector是否为空
        System.out.println("vec.isEmpty():"+vec.isEmpty());
    }
}

Stack

package java.util;  

public
class Stack<E> extends Vector<E> {  

    //无参构造函数
    public Stack() {
    }  

    /**
     * Pushes an item onto the top of this stack. This has exactly
     * the same effect as:
     * addElement(item)
    */
    public E push(E item) {
        addElement(item);  

        return item;
    }  

    /**
     * Removes the object at the top of this stack and returns that
     * object as the value of this function.
     */
    public synchronized E pop() {
        E       obj;
        int     len = size();  

        obj = peek();
        removeElementAt(len - 1);  

        return obj;
    }  

    /**
     * Looks at the object at the top of this stack without removing it
     * from the stack.
     */
    public synchronized E peek() {
        int     len = size();  

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }  

    /**
     * Tests if this stack is empty.
     *
     */
    public boolean empty() {
        return size() == 0;
    }  

    /**
     * Returns the 1-based position where an object is on this stack.
     * If the object o occurs as an item in this stack, this
     * method returns the distance from the top of the stack of the
     * occurrence nearest the top of the stack; the topmost item on the
     * stack is considered to be at distance 1. The equals
     * method is used to compare o to the
     * items in this stack.
     */
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);  

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }  

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 1224463164541339165L;
}
import java.util.Stack;

public class StackTest {

  /**
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Stack<String> stack = new Stack<String>();
    stack.add("China");
    stack.add("Japan");
    stack.add("Russia");
    stack.add("England");

    System.out.println(stack.size()+"<="+stack.capacity());
    System.out.println(stack.elementAt(0));
    System.out.println(stack.get(0));
    System.out.println(stack.peek());
    System.out.println(stack.push("France"));
    System.out.println(stack.pop());
    System.out.println(stack.iterator());
    System.out.println(stack.empty());
    System.out.println(stack.isEmpty());
         System.out.println(stack.search("Russia"));
  }

}

Stack类继承了Vector类,而Vector类继承了AbstractList抽象类,实现了List接口,Cloneable接口,RandomAcces接口以及Serializable接口,需要指出的Vector内部还有两个内部类ListItr和Itr,Itr在继承Vector的同时实现了Iterator接口,而ListItr在继承了Itr类的同时实现了ListIterator接口。

通过Stack类发现含有的方法有pop(),peek(),push(Object),search(Object),empty()方法,其他值的方法是从Vector类继承而来,通过源码可以发现Vector有几个属性值:
protected Object[] elementData ,
protected int elementCount ;
protected int capacityIncrement ;
private static final int MAX_ARRAY_SIZE = 2147483639 ;
通过这几属性我们可以发现,Stack底层是采用数组来实现的,elementData用于保存Stack中的每个元素;
elementCount用于动态的保存元素的个数,
capacityIncrement用来保存Stack的容量(一般情况下应该是大于elementCount);
MAX_ARRAY_SIZE 用于限制Stack能够保存的最大值数量。

public synchronized void removeElementAt(int paramInt) {
    this.modCount += 1;
    if (paramInt >= this.elementCount)
      throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
          + this.elementCount);
    if (paramInt < 0)
      throw new ArrayIndexOutOfBoundsException(paramInt);
    int i = this.elementCount - paramInt - 1;
    if (i > 0)
      System.arraycopy(this.elementData, paramInt + 1, this.elementData,
          paramInt, i);
    this.elementCount -= 1;
    this.elementData[this.elementCount] = null;
  }
removeElementAt()方法用于移除某个位置的元素,需要指出元素的位置,这个方法来之与Stack的父类Vector;通过代码我们可以发现它的实现是首先判断参数是否合法然后将这个位置前的所有元素都向后移动了一位,而且把元素的个数-1,最后把原来位置最上面的那个元素置为空,从而实现了删除某个元素的操作。
public synchronized E elementAt(int paramInt) {
    if (paramInt >= this.elementCount)
      throw new ArrayIndexOutOfBoundsException(paramInt + " >= "
          + this.elementCount);
    return elementData(paramInt);
  }
elementAt(int paramInt)首先判断参数是否合法,然后就直接调用elementData(paramInt)返回具体的对象值
public synchronized E peek() {
    int i = size();
    if (i == 0)
      throw new EmptyStackException();
    return elementAt(i - 1);
  }
peek()只是获取了第一个位置的元素的值(Stack的下标和数组保持一致都是从0开始,最大到元素总数-1)
public synchronized E pop() {
    int i = size();
    Object localObject = peek();
    removeElementAt(i - 1);
    return localObject;
  }
pop()方法的实现是首先获取Stack的元素数量,然后调用peek()方法获取栈顶的第一个元素,然后调用removeElementAt(int)删除栈顶元素,最后将元素的值返回。
public synchronized void addElement(E paramE) {
    this.modCount += 1;
    ensureCapacityHelper(this.elementCount + 1);
    this.elementData[(this.elementCount++)] = paramE;
  }
  addElement(E)方法是个很重要的方法,因为它实现了元素的添加。它在添加元素的时候首先将modCount加1,ensureCapacityHelper()主要用于保障Stack的容量,如果超过当前容量则调用grow()方法进行容量增加,如果操作最大的容量MAX_ARRAY_SIZE就会抛出异常。第三步才会实现元素的添加,就是i将该元素添加到栈顶,并且将元素的数目加1;
public synchronized int search(Object paramObject) {
    int i = lastIndexOf(paramObject);
    if (i >= 0)
      return (size() - i);
    return -1;
  }
  该方法返回所查找对象所处的位置,如果不存在在返回-1;通过代码可以发现它的实现过程是这样的,首先通过lastLindexOf(Object)方法返回从栈底到栈顶最下面的的那个元素的下标,然后利用元素的总数目减去所处的下标就得到了元素的位置(),并且返回否则返回-1;(需要注意的改位置返回的是从栈顶到栈底开始所处的位置,栈顶元素的位置为1)
public boolean empty() {
    return (size() == 0);
  }
直接返回元素的数目与0比较的关系,size()方法是通过this.elementCount返回了栈元素的数目。

Vector底层是一个数组,说明Stack的实现是通过数组来实现的,然后通过对数组的操作来模仿栈的各种功能。而且在源码中Vector的很多方法都是synchronized 的,也就是说是线程安全,所以说在多线程中是可以安全使用的,不过这样效率上肯定是会降低的

HashTable

Hashtable同样是基于哈希表实现的,同样 每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。Hashtable同样 实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆 。

package java.util;
import java.io.*;  

public class Hashtable<K,V>
  extends Dictionary<K,V>
  implements Map<K,V>, Cloneable, java.io.Serializable {  

  // 保存key-value的数组。
  // Hashtable同样采用单链表解决冲突,每一个Entry本质上是一个单向链表
  private transient Entry[] table;  

  // Hashtable中键值对的数量
  private transient int count;  

  // 阈值,用于判断是否需要调整Hashtable的容量(threshold = 容量*加载因子)
  private int threshold;  

  // 加载因子
  private float loadFactor;  

  // Hashtable被改变的次数,用于fail-fast机制的实现
  private transient int modCount = 0;  

  // 序列版本号
  private static final long serialVersionUID = 1421746759512286392L;  

  // 指定“容量大小”和“加载因子”的构造函数
  public Hashtable(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
      throw new IllegalArgumentException("Illegal Capacity: "+
                         initialCapacity);
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
      throw new IllegalArgumentException("Illegal Load: "+loadFactor);  

    if (initialCapacity==0)
      initialCapacity = 1;
    this.loadFactor = loadFactor;
    table = new Entry[initialCapacity];
    threshold = (int)(initialCapacity * loadFactor);
  }  

  // 指定“容量大小”的构造函数
  public Hashtable(int initialCapacity) {
    this(initialCapacity, 0.75f);
  }  

  // 默认构造函数。
  public Hashtable() {
    // 默认构造函数,指定的容量大小是11;加载因子是0.75
    this(11, 0.75f);
  }  

  // 包含“子Map”的构造函数
  public Hashtable(Map<? extends K, ? extends V> t) {
    this(Math.max(2*t.size(), 11), 0.75f);
    // 将“子Map”的全部元素都添加到Hashtable中
    putAll(t);
  }  

  public synchronized int size() {
    return count;
  }  

  public synchronized boolean isEmpty() {
    return count == 0;
  }  

  // 返回“所有key”的枚举对象
  public synchronized Enumeration<K> keys() {
    return this.<K>getEnumeration(KEYS);
  }  

  // 返回“所有value”的枚举对象
  public synchronized Enumeration<V> elements() {
    return this.<V>getEnumeration(VALUES);
  }  

  // 判断Hashtable是否包含“值(value)”
  public synchronized boolean contains(Object value) {
    //注意,Hashtable中的value不能是null,
    // 若是null的话,抛出异常!
    if (value == null) {
      throw new NullPointerException();
    }  

    // 从后向前遍历table数组中的元素(Entry)
    // 对于每个Entry(单向链表),逐个遍历,判断节点的值是否等于value
    Entry tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
      for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
        if (e.value.equals(value)) {
          return true;
        }
      }
    }
    return false;
  }  

  public boolean containsValue(Object value) {
    return contains(value);
  }  

  // 判断Hashtable是否包含key
  public synchronized boolean containsKey(Object key) {
    Entry tab[] = table;
    //计算hash值,直接用key的hashCode代替
    int hash = key.hashCode();
    // 计算在数组中的索引值
    int index = (hash & 0x7FFFFFFF) % tab.length;
    // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return true;
      }
    }
    return false;
  }  

  // 返回key对应的value,没有的话返回null
  public synchronized V get(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    // 计算索引值,
    int index = (hash & 0x7FFFFFFF) % tab.length;
    // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return e.value;
      }
    }
    return null;
  }  

  // 调整Hashtable的长度,将长度变成原来的2倍+1
  protected void rehash() {
    int oldCapacity = table.length;
    Entry[] oldMap = table;  

    //创建新容量大小的Entry数组
    int newCapacity = oldCapacity * 2 + 1;
    Entry[] newMap = new Entry[newCapacity];  

    modCount++;
    threshold = (int)(newCapacity * loadFactor);
    table = newMap;  

    //将“旧的Hashtable”中的元素复制到“新的Hashtable”中
    for (int i = oldCapacity ; i-- > 0 ;) {
      for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
        Entry<K,V> e = old;
        old = old.next;
        //重新计算index
        int index = (e.hash & 0x7FFFFFFF) % newCapacity;
        e.next = newMap[index];
        newMap[index] = e;
      }
    }
  }  

  // 将“key-value”添加到Hashtable中
  public synchronized V put(K key, V value) {
    // Hashtable中不能插入value为null的元素!!!
    if (value == null) {
      throw new NullPointerException();
    }  

    // 若“Hashtable中已存在键为key的键值对”,
    // 则用“新的value”替换“旧的value”
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        V old = e.value;
        e.value = value;
        return old;
        }
    }  

    // 若“Hashtable中不存在键为key的键值对”,
    // 将“修改统计数”+1
    modCount++;
    //  若“Hashtable实际容量” > “阈值”(阈值=总的容量 * 加载因子)
    //  则调整Hashtable的大小
    if (count >= threshold) {
      rehash();  

      tab = table;
      index = (hash & 0x7FFFFFFF) % tab.length;
    }  

    //将新的key-value对插入到tab[index]处(即链表的头结点)
    Entry<K,V> e = tab[index];
    tab[index] = new Entry<K,V>(hash, key, value, e);
    count++;
    return null;
  }  

  // 删除Hashtable中键为key的元素
  public synchronized V remove(Object key) {
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;  

    //从table[index]链表中找出要删除的节点,并删除该节点。
    //因为是单链表,因此要保留带删节点的前一个节点,才能有效地删除节点
    for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        modCount++;
        if (prev != null) {
          prev.next = e.next;
        } else {
          tab[index] = e.next;
        }
        count--;
        V oldValue = e.value;
        e.value = null;
        return oldValue;
      }
    }
    return null;
  }  

  // 将“Map(t)”的中全部元素逐一添加到Hashtable中
  public synchronized void putAll(Map<? extends K, ? extends V> t) {
    for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
      put(e.getKey(), e.getValue());
  }  

  // 清空Hashtable
  // 将Hashtable的table数组的值全部设为null
  public synchronized void clear() {
    Entry tab[] = table;
    modCount++;
    for (int index = tab.length; --index >= 0; )
      tab[index] = null;
    count = 0;
  }  

  // 克隆一个Hashtable,并以Object的形式返回。
  public synchronized Object clone() {
    try {
      Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
      t.table = new Entry[table.length];
      for (int i = table.length ; i-- > 0 ; ) {
        t.table[i] = (table[i] != null)
        ? (Entry<K,V>) table[i].clone() : null;
      }
      t.keySet = null;
      t.entrySet = null;
      t.values = null;
      t.modCount = 0;
      return t;
    } catch (CloneNotSupportedException e) {
      throw new InternalError();
    }
  }  

  public synchronized String toString() {
    int max = size() - 1;
    if (max == -1)
      return "{}";  

    StringBuilder sb = new StringBuilder();
    Iterator<Map.Entry<K,V>> it = entrySet().iterator();  

    sb.append('{');
    for (int i = 0; ; i++) {
      Map.Entry<K,V> e = it.next();
      K key = e.getKey();
      V value = e.getValue();
      sb.append(key   == this ? "(this Map)" : key.toString());
      sb.append('=');
      sb.append(value == this ? "(this Map)" : value.toString());  

      if (i == max)
        return sb.append('}').toString();
      sb.append(", ");
    }
  }  

  // 获取Hashtable的枚举类对象
  // 若Hashtable的实际大小为0,则返回“空枚举类”对象;
  // 否则,返回正常的Enumerator的对象。
  private <T> Enumeration<T> getEnumeration(int type) {
  if (count == 0) {
    return (Enumeration<T>)emptyEnumerator;
  } else {
    return new Enumerator<T>(type, false);
  }
  }  

  // 获取Hashtable的迭代器
  // 若Hashtable的实际大小为0,则返回“空迭代器”对象;
  // 否则,返回正常的Enumerator的对象。(Enumerator实现了迭代器和枚举两个接口)
  private <T> Iterator<T> getIterator(int type) {
    if (count == 0) {
      return (Iterator<T>) emptyIterator;
    } else {
      return new Enumerator<T>(type, true);
    }
  }  

  // Hashtable的“key的集合”。它是一个Set,没有重复元素
  private transient volatile Set<K> keySet = null;
  // Hashtable的“key-value的集合”。它是一个Set,没有重复元素
  private transient volatile Set<Map.Entry<K,V>> entrySet = null;
  // Hashtable的“key-value的集合”。它是一个Collection,可以有重复元素
  private transient volatile Collection<V> values = null;  

  // 返回一个被synchronizedSet封装后的KeySet对象
  // synchronizedSet封装的目的是对KeySet的所有方法都添加synchronized,实现多线程同步
  public Set<K> keySet() {
    if (keySet == null)
      keySet = Collections.synchronizedSet(new KeySet(), this);
    return keySet;
  }  

  // Hashtable的Key的Set集合。
  // KeySet继承于AbstractSet,所以,KeySet中的元素没有重复的。
  private class KeySet extends AbstractSet<K> {
    public Iterator<K> iterator() {
      return getIterator(KEYS);
    }
    public int size() {
      return count;
    }
    public boolean contains(Object o) {
      return containsKey(o);
    }
    public boolean remove(Object o) {
      return Hashtable.this.remove(o) != null;
    }
    public void clear() {
      Hashtable.this.clear();
    }
  }  

  // 返回一个被synchronizedSet封装后的EntrySet对象
  // synchronizedSet封装的目的是对EntrySet的所有方法都添加synchronized,实现多线程同步
  public Set<Map.Entry<K,V>> entrySet() {
    if (entrySet==null)
      entrySet = Collections.synchronizedSet(new EntrySet(), this);
    return entrySet;
  }  

  // Hashtable的Entry的Set集合。
  // EntrySet继承于AbstractSet,所以,EntrySet中的元素没有重复的。
  private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
      return getIterator(ENTRIES);
    }  

    public boolean add(Map.Entry<K,V> o) {
      return super.add(o);
    }  

    // 查找EntrySet中是否包含Object(0)
    // 首先,在table中找到o对应的Entry链表
    // 然后,查找Entry链表中是否存在Object
    public boolean contains(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry entry = (Map.Entry)o;
      Object key = entry.getKey();
      Entry[] tab = table;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;  

      for (Entry e = tab[index]; e != null; e = e.next)
        if (e.hash==hash && e.equals(entry))
          return true;
      return false;
    }  

    // 删除元素Object(0)
    // 首先,在table中找到o对应的Entry链表
    // 然后,删除链表中的元素Object
    public boolean remove(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
      K key = entry.getKey();
      Entry[] tab = table;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;  

      for (Entry<K,V> e = tab[index], prev = null; e != null;
         prev = e, e = e.next) {
        if (e.hash==hash && e.equals(entry)) {
          modCount++;
          if (prev != null)
            prev.next = e.next;
          else
            tab[index] = e.next;  

          count--;
          e.value = null;
          return true;
        }
      }
      return false;
    }  

    public int size() {
      return count;
    }  

    public void clear() {
      Hashtable.this.clear();
    }
  }  

  // 返回一个被synchronizedCollection封装后的ValueCollection对象
  // synchronizedCollection封装的目的是对ValueCollection的所有方法都添加synchronized,实现多线程同步
  public Collection<V> values() {
  if (values==null)
    values = Collections.synchronizedCollection(new ValueCollection(),
                            this);
    return values;
  }  

  // Hashtable的value的Collection集合。
  // ValueCollection继承于AbstractCollection,所以,ValueCollection中的元素可以重复的。
  private class ValueCollection extends AbstractCollection<V> {
    public Iterator<V> iterator() {
    return getIterator(VALUES);
    }
    public int size() {
      return count;
    }
    public boolean contains(Object o) {
      return containsValue(o);
    }
    public void clear() {
      Hashtable.this.clear();
    }
  }  

  // 重新equals()函数
  // 若两个Hashtable的所有key-value键值对都相等,则判断它们两个相等
  public synchronized boolean equals(Object o) {
    if (o == this)
      return true;  

    if (!(o instanceof Map))
      return false;
    Map<K,V> t = (Map<K,V>) o;
    if (t.size() != size())
      return false;  

    try {
      // 通过迭代器依次取出当前Hashtable的key-value键值对
      // 并判断该键值对,存在于Hashtable中。
      // 若不存在,则立即返回false;否则,遍历完“当前Hashtable”并返回true。
      Iterator<Map.Entry<K,V>> i = entrySet().iterator();
      while (i.hasNext()) {
        Map.Entry<K,V> e = i.next();
        K key = e.getKey();
        V value = e.getValue();
        if (value == null) {
          if (!(t.get(key)==null && t.containsKey(key)))
            return false;
        } else {
          if (!value.equals(t.get(key)))
            return false;
        }
      }
    } catch (ClassCastException unused)   {
      return false;
    } catch (NullPointerException unused) {
      return false;
    }  

    return true;
  }  

  // 计算Entry的hashCode
  // 若 Hashtable的实际大小为0 或者 加载因子<0,则返回0。
  // 否则,返回“Hashtable中的每个Entry的key和value的异或值 的总和”。
  public synchronized int hashCode() {
    int h = 0;
    if (count == 0 || loadFactor < 0)
      return h;  // Returns zero  

    loadFactor = -loadFactor;  // Mark hashCode computation in progress
    Entry[] tab = table;
    for (int i = 0; i < tab.length; i++)
      for (Entry e = tab[i]; e != null; e = e.next)
        h += e.key.hashCode() ^ e.value.hashCode();
    loadFactor = -loadFactor;  // Mark hashCode computation complete  

    return h;
  }  

  // java.io.Serializable的写入函数
  // 将Hashtable的“总的容量,实际容量,所有的Entry”都写入到输出流中
  private synchronized void writeObject(java.io.ObjectOutputStream s)
    throws IOException
  {
    // Write out the length, threshold, loadfactor
    s.defaultWriteObject();  

    // Write out length, count of elements and then the key/value objects
    s.writeInt(table.length);
    s.writeInt(count);
    for (int index = table.length-1; index >= 0; index--) {
      Entry entry = table[index];  

      while (entry != null) {
      s.writeObject(entry.key);
      s.writeObject(entry.value);
      entry = entry.next;
      }
    }
  }  

  // java.io.Serializable的读取函数:根据写入方式读出
  // 将Hashtable的“总的容量,实际容量,所有的Entry”依次读出
  private void readObject(java.io.ObjectInputStream s)
     throws IOException, ClassNotFoundException
  {
    // Read in the length, threshold, and loadfactor
    s.defaultReadObject();  

    // Read the original length of the array and number of elements
    int origlength = s.readInt();
    int elements = s.readInt();  

    // Compute new size with a bit of room 5% to grow but
    // no larger than the original size.  Make the length
    // odd if it's large enough, this helps distribute the entries.
    // Guard against the length ending up zero, that's not valid.
    int length = (int)(elements * loadFactor) + (elements / 20) + 3;
    if (length > elements && (length & 1) == 0)
      length--;
    if (origlength > 0 && length > origlength)
      length = origlength;  

    Entry[] table = new Entry[length];
    count = 0;  

    // Read the number of elements and then all the key/value objects
    for (; elements > 0; elements--) {
      K key = (K)s.readObject();
      V value = (V)s.readObject();
        // synch could be eliminated for performance
        reconstitutionPut(table, key, value);
    }
    this.table = table;
  }  

  private void reconstitutionPut(Entry[] tab, K key, V value)
    throws StreamCorruptedException
  {
    if (value == null) {
      throw new java.io.StreamCorruptedException();
    }
    // Makes sure the key is not already in the hashtable.
    // This should not happen in deserialized version.
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        throw new java.io.StreamCorruptedException();
      }
    }
    // Creates the new entry.
    Entry<K,V> e = tab[index];
    tab[index] = new Entry<K,V>(hash, key, value, e);
    count++;
  }  

  // Hashtable的Entry节点,它本质上是一个单向链表。
  // 也因此,我们才能推断出Hashtable是由拉链法实现的散列表
  private static class Entry<K,V> implements Map.Entry<K,V> {
    // 哈希值
    int hash;
    K key;
    V value;
    // 指向的下一个Entry,即链表的下一个节点
    Entry<K,V> next;  

    // 构造函数
    protected Entry(int hash, K key, V value, Entry<K,V> next) {
      this.hash = hash;
      this.key = key;
      this.value = value;
      this.next = next;
    }  

    protected Object clone() {
      return new Entry<K,V>(hash, key, value,
          (next==null ? null : (Entry<K,V>) next.clone()));
    }  

    public K getKey() {
      return key;
    }  

    public V getValue() {
      return value;
    }  

    // 设置value。若value是null,则抛出异常。
    public V setValue(V value) {
      if (value == null)
        throw new NullPointerException();  

      V oldValue = this.value;
      this.value = value;
      return oldValue;
    }  

    // 覆盖equals()方法,判断两个Entry是否相等。
    // 若两个Entry的key和value都相等,则认为它们相等。
    public boolean equals(Object o) {
      if (!(o instanceof Map.Entry))
        return false;
      Map.Entry e = (Map.Entry)o;  

      return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
         (value==null ? e.getValue()==null : value.equals(e.getValue()));
    }  

    public int hashCode() {
      return hash ^ (value==null ? 0 : value.hashCode());
    }  

    public String toString() {
      return key.toString()+"="+value.toString();
    }
  }  

  private static final int KEYS = 0;
  private static final int VALUES = 1;
  private static final int ENTRIES = 2;  

  // Enumerator的作用是提供了“通过elements()遍历Hashtable的接口” 和 “通过entrySet()遍历Hashtable的接口”。
  private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
    // 指向Hashtable的table
    Entry[] table = Hashtable.this.table;
    // Hashtable的总的大小
    int index = table.length;
    Entry<K,V> entry = null;
    Entry<K,V> lastReturned = null;
    int type;  

    // Enumerator是 “迭代器(Iterator)” 还是 “枚举类(Enumeration)”的标志
    // iterator为true,表示它是迭代器;否则,是枚举类。
    boolean iterator;  

    // 在将Enumerator当作迭代器使用时会用到,用来实现fail-fast机制。
    protected int expectedModCount = modCount;  

    Enumerator(int type, boolean iterator) {
      this.type = type;
      this.iterator = iterator;
    }  

    // 从遍历table的数组的末尾向前查找,直到找到不为null的Entry。
    public boolean hasMoreElements() {
      Entry<K,V> e = entry;
      int i = index;
      Entry[] t = table;
      /* Use locals for faster loop iteration */
      while (e == null && i > 0) {
        e = t[--i];
      }
      entry = e;
      index = i;
      return e != null;
    }  

    // 获取下一个元素
    // 注意:从hasMoreElements() 和nextElement() 可以看出“Hashtable的elements()遍历方式”
    // 首先,从后向前的遍历table数组。table数组的每个节点都是一个单向链表(Entry)。
    // 然后,依次向后遍历单向链表Entry。
    public T nextElement() {
      Entry<K,V> et = entry;
      int i = index;
      Entry[] t = table;
      /* Use locals for faster loop iteration */
      while (et == null && i > 0) {
        et = t[--i];
      }
      entry = et;
      index = i;
      if (et != null) {
        Entry<K,V> e = lastReturned = entry;
        entry = e.next;
        return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
      }
      throw new NoSuchElementException("Hashtable Enumerator");
    }  

    // 迭代器Iterator的判断是否存在下一个元素
    // 实际上,它是调用的hasMoreElements()
    public boolean hasNext() {
      return hasMoreElements();
    }  

    // 迭代器获取下一个元素
    // 实际上,它是调用的nextElement()
    public T next() {
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
      return nextElement();
    }  

    // 迭代器的remove()接口。
    // 首先,它在table数组中找出要删除元素所在的Entry,
    // 然后,删除单向链表Entry中的元素。
    public void remove() {
      if (!iterator)
        throw new UnsupportedOperationException();
      if (lastReturned == null)
        throw new IllegalStateException("Hashtable Enumerator");
      if (modCount != expectedModCount)
        throw new ConcurrentModificationException();  

      synchronized(Hashtable.this) {
        Entry[] tab = Hashtable.this.table;
        int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;  

        for (Entry<K,V> e = tab[index], prev = null; e != null;
           prev = e, e = e.next) {
          if (e == lastReturned) {
            modCount++;
            expectedModCount++;
            if (prev == null)
              tab[index] = e.next;
            else
              prev.next = e.next;
            count--;
            lastReturned = null;
            return;
          }
        }
        throw new ConcurrentModificationException();
      }
    }
  }  

  private static Enumeration emptyEnumerator = new EmptyEnumerator();
  private static Iterator emptyIterator = new EmptyIterator();  

  // 空枚举类
  // 当Hashtable的实际大小为0;此时,又要通过Enumeration遍历Hashtable时,返回的是“空枚举类”的对象。
  private static class EmptyEnumerator implements Enumeration<Object> {  

    EmptyEnumerator() {
    }  

    // 空枚举类的hasMoreElements() 始终返回false
    public boolean hasMoreElements() {
      return false;
    }  

    // 空枚举类的nextElement() 抛出异常
    public Object nextElement() {
      throw new NoSuchElementException("Hashtable Enumerator");
    }
  }  

  // 空迭代器
  // 当Hashtable的实际大小为0;此时,又要通过迭代器遍历Hashtable时,返回的是“空迭代器”的对象。
  private static class EmptyIterator implements Iterator<Object> {  

    EmptyIterator() {
    }  

    public boolean hasNext() {
      return false;
    }  

    public Object next() {
      throw new NoSuchElementException("Hashtable Iterator");
    }  

    public void remove() {
      throw new IllegalStateException("Hashtable Iterator");
    }  

  }
}

与HashMap的比较来总结。
1、二者的存储结构和解决冲突的方法都是相同的。
2、HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
3、 Hashtable中key和value都不允许为null,而HashMap中key和value都允许为null(key只能有一个为null,而value则可以有多个为null)。
但是如果在Hashtable中有类似put(null,null)的操作,编译同样可以通过,因为key和value都是Object类型,但运行时会抛出NullPointerException异常,这是JDK的规范规定的。

// 判断Hashtable是否包含“值(value)”
  public synchronized boolean contains(Object value) {
    //注意,Hashtable中的value不能是null,
    // 若是null的话,抛出异常!
    if (value == null) {
      throw new NullPointerException();
    }  

    // 从后向前遍历table数组中的元素(Entry)
    // 对于每个Entry(单向链表),逐个遍历,判断节点的值是否等于value
    Entry tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
      for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
        if (e.value.equals(value)) {
          return true;
        }
      }
    }
    return false;
  }  

  public boolean containsValue(Object value) {
    return contains(value);
  }  

  // 判断Hashtable是否包含key
  public synchronized boolean containsKey(Object key) {
    Entry tab[] = table;
    //计算hash值,直接用key的hashCode代替
    int hash = key.hashCode();
    // 计算在数组中的索引值
    int index = (hash & 0x7FFFFFFF) % tab.length;
    // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
      if ((e.hash == hash) && e.key.equals(key)) {
        return true;
      }
    }
    return false;
  }
很明显,如果value为null,会直接抛出 NullPointerException异常,但源码中并没有对key是否为null判断,有点小不解!不过 NullPointerException 属于 RuntimeException异常,是可以由JVM自动抛出的,也许对key的值在JVM中有所限制吧

4、Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
5、Hashtable计算hash值,直接用key的hashCode(),HashMap重新计算了key的hash值,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模, &0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而 &0x7FFFFFFF后,只有符号外改变,而后面的位都不变。

Collections.synchronizedXXX工厂方法

@NotThreadSafe
class BadListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());  

    public synchronized boolean putIfAbsent(E x) {
        boolean absent = !list.contains(x);
        if (absent)
            list.add(x);
        return absent;
    }
}  

不仔细的看,还以为这个类是线程安全的,因为putIfAbsent方法加了synchronized。不过细心的同学就会发现原来putIfAbsent方法和List并不是使用的同一个锁对象,List使用的锁对象并不是BadListHelper,而是list。假如A线程进入putIfAbsent方法,list这个锁并没有被获取(A线程获取的是 BadListHelper这个对象),所以其他线程还能够获得list锁对象来改变list对象。boolean absent = !list.contains(x);当线程到这串代码结束时,其他线程获得list锁对象,从而就能调用list的方法来改变list对象,这时候就可能导致!list.contains(x)改变,即域absent并不是A线程得到的布尔类型。所以这个类并不是线程安全的。

@ThreadSafe
class GoodListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());  

    public boolean putIfAbsent(E x) {
        synchronized (list) {  //获得list锁对象,其他线程将不能获得list锁来来改变list对象。
            boolean absent = !list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
}  
时间: 2024-10-10 20:08:54

java-并发-同步容器的相关文章

Java 并发/多线程教程(十二)-JAVA同步块

本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 一个Java同步块标记一个方法或一个代码块作为同步.可以使用Java同步块来避免竞态条件. java同步关键字       在Java中同步的块被标记为Synchronized关键字.Java中的同步块在某些对象上是同步的.在同一对象上同步的所有同步块只能在同一时间内执行一个线程.所有试图进入同步块的其他线程都被阻塞,直到同步块中的线程退出该块. Synchronized关键字可以

深入解析Java并发程序中线程的同步与线程锁的使用_java

synchronized关键字 synchronized,我们谓之锁,主要用来给方法.代码块加锁.当某个方法或者代码块使用synchronized时,那么在同一时刻至多仅有有一个线程在执行该段代码.当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段.但是,其余线程是可以访问该对象中的非加锁代码块的. synchronized主要包括两种方法:synchronized 方法.synchronized 块. synchron

Java并发集合的实现原理

本文简要介绍Java并发编程方面常用的类和集合,并介绍下其实现原理. AtomicInteger 可以用原子方式更新int值.类 AtomicBoolean.AtomicInteger.AtomicLong 和 AtomicReference 的实例各自提供对相应类型单个变量的访问和更新.基本的原理都是使用CAS操作: boolean compareAndSet(expectedValue, updateValue); 如果此方法(在不同的类间参数类型也不同)当前保持expectedValue,

Java并发编程相关面试问题

基础概念 1.什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)? 原子操作(atomic operation)意为"不可被中断的一个或一系列操作" .处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作. 在Java中可以通过锁和循环CAS的方式来实现原子操作. CAS操作--Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作. 原子操作是

大数据量下高并发同步的讲解(不看,保证你后悔)(转)

  对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了.而并发问题是绝大部分的程序员头疼的问题, 但话又说回来了,既然逃避不掉,那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧. 为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步 1.同步和异步的区别和联系 所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到 返回的值或消息后才往下执行其它的命令. 异步,执行完函数或方法后

Java并发编程:并发容器之CopyOnWriteArrayList

原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略.从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet.CopyOnW

java并发编程实践笔记

1, 保证线程安全的三种方法:     a, 不要跨线程访问共享变量     b, 使共享变量是final类型的     c, 将共享变量的操作加上同步 2, 一开始就将类设计成线程安全的, 比在后期重新修复它,更容易. 3, 编写多线程程序, 首先保证它是正确的, 其次再考虑性能. 4, 无状态或只读对象永远是线程安全的. 5, 不要将一个共享变量裸露在多线程环境下(无同步或不可变性保护) 6, 多线程环境下的延迟加载需要同步的保护, 因为延迟加载会造成对象重复实例化 7, 对于volatil

Java并发编程之阻塞队列详解_java

1.什么是阻塞队列? 队列是一种数据结构,它有两个基本操作:在队列尾部加入一个元素,从队列头部移除一个元素.阻塞队里与普通的队列的区别在于,普通队列不会对当前线程产生阻塞,在面对类似消费者-生产者模型时,就必须额外的实现同步策略以及线程间唤醒策略.使用阻塞队列,就会对当前线程产生阻塞,当队列是空时,从队列中获取元素的操作将会被阻塞,当队列是满时,往队列里添加元素的操作也会被阻塞. 2.主要的阻塞队列及其方法 java.util.concurrent包下提供主要的几种阻塞队列,主要有以下几个: 1

Java并发编程:阻塞队列

我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程序提供了很大的方便.今天我们来讨论另外一类容器:阻塞队列. 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(LinkedList是双向链表,它实现了Dequeue接口). 使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,