本文作者:王一飞,叩丁狼高级讲师。原创文章,转载请注明出处。
实际开发中, 我们使用频率最高的容器估计是list集合,那肯定会遇并发操作.那该如何保证在多线程并发的环境下安全,高效的使用list集合呢?好,这就是今天我们聊话题:并发中的List集合.
List: 有序集合(也称为序列 )。用户可以精确控制列表中每个元素的插入位置。 也可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。 常用方法有:
添加: boolean add(E e);
删除: boolean remove(Object o);
修改: E set(int index, E element);
查询: E get(int index);
下面是List接口的实现体系:
常见的实现类:
ArrayList : 可调整大小的数组的实现List接口
LinkedList :实现List和Deque接口的双链表
Vector: 实现了可扩展的对象数组,是同步的ArrayList
CopyOnWriteArrayList:带有快照功能的读写安全并发容器类
Stack:最先进先出(LIFO)堆栈的对象
List集合实现类众多,本篇挑出具有代表选3个实现类来逐一分析, 在并发环境下,它们的使用注意.
ArrayList 类其下所有操作方法都没有使用任何加锁痕迹,这表明该类是一个线程不安全类.比如下面添加的方法:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
在多线程环境下, 如果使用ArrayList进行操作时,可能存在线程不安全的隐患, 比如下面的例子:
需求:事先准备好一个集合list, 一个线程删除最后一个元素, 一个线程清空list集合
public class App {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
new Thread(new Runnable() {
public void run() {
//集合大小
int len = list.size();
try {
//睡5s
Thread.sleep(