java中ArrayList、LinkedList、Vector的区别

ArrayList、LinkedList、Vector这三个类都实现了List接口。


ArrayList是一个可以处理变长数组的类型,可以存放任意类型的对象。ArrayList的所有方法都是默认在单一线程下进行的,因此ArrayList不具有线程安全性。

LinkedList可以看做为一个双向链表,LinkedList也是线程不安全的,在LinkedList的内部实现中,并不是用普通的数组来存放数据的,而是使用结点<Node>来存放数据的,有一个指向链表头的结点first和一个指向链表尾的结点last。LinkedList的插入方法的效率要高于ArrayList,但是查询的效率要低一点。

Vector也是一个类似于ArrayList的可变长度的数组类型,它的内部也是使用数组来存放数据对象的。值得注意的是Vector与ArrayList唯一的区别是,Vector是线程安全的。在扩展容量的时候,Vector是扩展为原来的2倍,而ArrayList是扩展为原来的1.5倍。


为什么说ArrayListLinkedList是线程不安全的,而Vector是线程安全的呢?

首先来看下线程安全不安全的解释:

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

阅读Vector类的源码容易知道,Vector的方法前面加了synchronized关键字,意思指同步。无论多少线程执行此程序,当一个线程没有执行完的时候,其他线程只有等待。所以它被设计成了线程安全的,但是在效率上并没有ArrayList高效。例如Vector类的add方法源码:

public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

对于ArrayList,例如在添加元素的时候,调用ArrayList的add方法,源码如下:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
可以看到,在向ArrayList添加元素的时候,此条语句
elementData[size++] = e;

是先执行elementData[size] = e,然后执行size = size + 1,这是分两步来完成的。在单线程下运行当然是没有问题的,但是如果是多个线程同时执行,假设线程A执行完elementData[size] = e时,CPU暂停执行线程A去执行线程B,此时ArrayList的size并没有加一,这时在ArrayList中线程B也执行elementData[size] = e,就会把线程A刚才赋的值覆盖掉,而此时,A线程和B线程先后执行size++,便会出现值为null的情况;当然还有其他异常情况,如果需要在多线程中使用,可以采用下面语句创建ArrayList对象。

List<Object> list =Collections.synchronizedList(new ArrayList<Object>());
至于LinkedList为什么线程不安全,本人没分析过,有兴趣的朋友可以自己阅读源码!

猜你喜欢

转载自blog.csdn.net/csdn15698845876/article/details/79480066