集合之Map和List线程安全问题

一、Map常见的子类有:

1、HashMap:
          底层数据结构是哈希表,线程不安全,允许null键和null值

2、Hashtable:
          线程安全的,不允许null键和null值,效率低,给整个方法添加synchronized,太笨重

3、LinkedHashMap:
          底层数据结构是链表和哈希表,由链表保证有序(存储和取出的顺序一致),哈希表保证唯一,线程不安全

4、TreeMap:
          底层数据结构是红黑树(一种自平衡的二叉树),可以按照某种规则进行排序,自然排序和选择器排序,线程不安全

5、ConcurrentHashMap:
        ● 线程安全的,不允许null键和null值

        ● 对与多线程的操作,介于HashMap与Hashtable之间。

        ● 内部采用"锁分段"机制代替Hashtable的独占锁。进而提高性能。

       【查看源码:Hashtable是给整个方法上面添加synchronized,而ConcurrentHashMap是给可能出现线程安全问题的代码用同步代码块的方式加锁】

        ● 获取操作(包括 get)通常不会受阻塞

默认初始容量是16
加载因子是0.75,即当 元素个数 超过 容量长度的0.75倍 (即16*0.75=12)时,进行扩容

线程安全的LIST

List<Integer> vector = new Vector<>();
List<Integer> listSyn = Collections.synchronizedList(new ArrayList<>());
List<Integer> copyList = new CopyOnWriteArrayList<>();

  

ArrayList线程不安全:主要是多线程在写入数据时,会有重复写入的问题

Vector线程安全:主要是在添加元素的时候,加上了synchronized

public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);

E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}


Collections.synchronizedList:主要是一个大的集合框架里面也是synchronized

public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
CopyOnWriteArrayList:主要是使用ReentrantLock,每次添加元素都会复制旧的数据到新的数组里面,同时使用锁
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}


总结
ArrayList 单线程中使用

多线程中,并发在2000以内的使用Collections.synchronizedList;并发在2000以上的使用CopyOnWriteArrayList;Vector是JDK1.1版本就有的集合是一个重量级的,不建议使用。

posted @ 2022-08-31 19:03  张亮java  阅读(475)  评论(0编辑  收藏  举报