天天看点

面试题-List之ArrayList、Vector、SynchronizedList、CopyOnWriteArrayList

容器中的List在我们日常开发中,比较常用,而且也是面试的必考题,下面我们来说下List家族的各种实现;

1.ArrayList

ArrayList底层是数组实现,顺序插入,可以通过下标查找元素,速度很快,插入和删除元素很慢,非线程安全,比如在多线层的情况下add(),会出现覆盖情况;

面试题-List之ArrayList、Vector、SynchronizedList、CopyOnWriteArrayList
容易出现问题的地方在于,elementData[size++] = e;首先把元素赋值给数组,然后长度增加,当两个线程同时增加元素时,线程1拿到时间片赋值elementData[size] = 1,执行后失去时间片,线程2获得时间片,elementData[size] = 2,这样线程1的值就被线程给覆盖了,长度两次增加变成2,实际上第2个值是null,这样就出现了问题;同时遍历时需改也存在java.util.ConcurrentModificationException异常;
2.Vector    Vector底层也是数组,它和ArrayList的区别在于add、set、get方等法上都加了synchronized关键字,这样就保证了多线程下的线程安全问题,但是效率不如ArrayList;
3.SynchronizedList    SynchronizedList是容器工具包提供的包装同步类,List<String> stringList = Collections.synchronizedList(list);看下面的代码,他在set、get等方法内部加了同步代码块,synchronized (mutex) 锁住了传入的对象,但是效率没有太大的改变。           

复制

4.CopyOnWriteArrayList

CopyOnWriteArrayList是今天的主角,它是一个实现读写分离的容器,add时通过一个非公平锁加锁,然后复制现有数组为一个新的数组,再把新加入的元素添加到新数组中,把数组指针指向新数组,这样写输入保证了线程安全问题,使用可重入锁的非公平锁效率很高,读数据的时候,读现有的数组,不用加锁,效率提升很多,缺点是每次写入都要复制一个新的数组,会造成内存浪费,垃圾回收频繁等,适合读多写少的场景。

面试题-List之ArrayList、Vector、SynchronizedList、CopyOnWriteArrayList