目录

  • 一.并发容器的由来
  • 二.常用的Java并发容器
  • 1.ConcurrentHashMap
  • 2.CopyOnWriteArrayList
  • 3.CopyOnWriteArraySet
  • 4.ConcurrentLinkedQueue
  • 5.ConcurrentLinkedDeque


一.并发容器的由来

在java的集合容器体系中,常用的ArrayList、LinkedList、HashMap等都属于线程不安全的容器。为了适应多线程开发,java首先为我们提供了同步容器即通过synchronized关键字修饰整个代码块来保证线程安全。

常见的同步容器有:Vector、HashTable、Stack等

同步容器保证了线程的安全性,但是synchronized修饰整个代码片极大地降低了程序运行的效率,于是就有了效率更高,同时保证线程安全的并发容器

并发容器通过锁分段技术和CAS算法( Compare And Swap)保证线程安全和运行效率。

锁分段技术即仅仅在需要操作的位置进行同步,对于其他的部分则允许多线程并发执行。

CAS算法原理图解

国内 JAVA 容器排名_数组


二.常用的Java并发容器

java并发容器都在java.util.concurrent包下:

1.ConcurrentHashMap

做为并发版的HashMap,其底层结构依然是哈希表结构。在jdk1.7版本中ConcurrentHashMap依靠锁分段技术实现并发编程,而在jdk1.8版本则是采用CAS算法实现。**

2.CopyOnWriteArrayList

做为并发版的ArrayList,底层结构也是数组。但与ArrayList不同的是,CopyOnWriteArrayList的底层数组加上了Volatile关键字,以保证可见性和有序性。

国内 JAVA 容器排名_数组_02

实现原理对读取操作不加锁限制,只对写(增删改)操作加锁,从而在保证一定线程安全的条件下同时提高了效率。因此CopyOnWriteArrayList读出来的数据有可能不是最新的数据。

国内 JAVA 容器排名_数组_03


国内 JAVA 容器排名_国内 JAVA 容器排名_04

正像CopyOnWriteArrayList命名的那样:CopyOnWrite在新增或者删除元素时CopyOnWriteArrayList都是复制一个新的数组进行操作,然后再用这个新数组替换原来的数组

国内 JAVA 容器排名_java_05

3.CopyOnWriteArraySet

HashSet的并发版本,底层基于CopyOnWriteArrayList实现。由于本身是做为HashSet的并发版本,所以内部元素也不允许重复。

当CopyOnWriteArraySet调用add方法时,将会调用CopyOnWriteArrayList的addIfAbsent方法遍历数组,判断待加入元素是否已存在。如果已经存在,返回false;否则将元素插入数组末尾并返回true

国内 JAVA 容器排名_java_06

public boolean add(E e) {
        return this.al.addIfAbsent(e);
    }
public boolean addIfAbsent(E e) {
        Object[] snapshot = this.getArray();
        return indexOfRange(e, snapshot, 0, snapshot.length) < 0 && this.addIfAbsent(e, snapshot);
    }

    private boolean addIfAbsent(E e, Object[] snapshot) {
        synchronized(this.lock) {
            Object[] current = this.getArray();
            int len = current.length;
            if (snapshot != current) {
                int common = Math.min(snapshot.length, len);

                for(int i = 0; i < common; ++i) {
                    if (current[i] != snapshot[i] && Objects.equals(e, current[i])) {
                        return false;
                    }
                }

                if (indexOfRange(e, current, common, len) >= 0) {
                    return false;
                }
            }

            Object[] newElements = Arrays.copyOf(current, len + 1);
            newElements[len] = e;
            this.setArray(newElements);
            return true;
        }
    }

4.ConcurrentLinkedQueue

基于单向链表实现的FIFO(First Input First Output)队列,做为Queue的并发版本。

5.ConcurrentLinkedDeque

基于双向链表实现的并发队列,既可以先进先出,也可以先进后出。