一、ConcurrentHashMap底层结构
二、ConcurrentHashMap类的成员变量
public class ConcurrentHashMap<K, V>extends AbstractMap<K, V>implements ConcurrentMap<K, V>, Serializable {// 数组最大容量private static final int MAXIMUM_CAPACITY = 1 << 30;// 数组初始容量private static final int DEFAULT_CAPACITY = 16;// 负载因子(超过就要扩容)private static final float LOAD_FACTOR = 0.75f;// 树化阈值(节点数超过阈值,需要把链表转换成红黑树)static final int TREEIFY_THRESHOLD = 8;// 反树化阈值(当红黑树节点数量小于此阈值,重新转换成链表)static final int UNTREEIFY_THRESHOLD = 6;// 转换成红黑树的最少元素数量static final int MIN_TREEIFY_CAPACITY = 64;// 特殊节点的哈希值static final int MOVED = -1; // 转移节点的哈希值static final int TREEBIN = -2; // 红黑树根节点的哈希值static final int RESERVED = -3; // 临时节点的哈希值// 节点类型数组transient volatile Node<K, V>[] table;// 备用数组,用于扩容private transient volatile Node<K, V>[] nextTable;// 元素个数(没有统计并发的操作)private transient volatile long baseCount;// 并发的元素个数(想要统计总数量,需要加上baseCount)private transient volatile CounterCell[] counterCells;/*** sizeCtl用来控制table的初始化和扩容操作的过程,其值大致如下:* -1 代表table正在初始化,其他线程应该交出CPU时间片* -N 表示有N-1个线程正在进行扩容操作,严格来说,当其为负数时,只用到其低16位,如果其低16位数值为M,此时有M-1个线程进行扩容* 大于0分两种情况:如果table未初始化,sizeCtl表示table需要初始化的大小;如果table初始化完成,sizeCtl表示table的容量,默认是table大小的0.75倍*/private transient volatile int sizeCtl;}
ConcurrentHashMap还定义了4个节点内部类,分别是链表节点Node、红黑树节点TreeNode、管理红黑树的容器TreeBin、扩容时的临时转移节点ForwardingNode
public class ConcurrentHashMap<K, V>extends AbstractMap<K, V>implements ConcurrentMap<K, V>, Serializable {/*** 链表节点类*/static class Node<K, V> implements Map.Entry<K, V> {final int hash;final K key;volatile V val;volatile Node<K, V> next;Node(int hash, K key, V val, Node<K, V> next) {this.hash = hash;this.key = key;this.val = val;this.next = next;}}/*** 红黑树节点类*/static final class TreeNode<K, V> extends Node<K, V> {TreeNode<K, V> parent;TreeNode<K, V> left;TreeNode<K, V> right;TreeNode<K, V> prev;boolean red;TreeNode(int hash, K key, V val, Node<K, V> next,TreeNode<K, V> parent) {super(hash, key, val, next);this.parent = parent;}}/*** 管理红黑树的容器*/static final class TreeBin<K, V> extends Node<K, V> {TreeNode<K, V> root;volatile TreeNode<K, V> first;volatile Thread waiter;volatile int lockState;}/*** 转移节点(扩容时使用)*/static final class ForwardingNode<K, V> extends Node<K, V> {final Node<K, V>[] nextTable;ForwardingNode(Node<K, V>[] tab) {super(MOVED, null, null, null);this.nextTable = tab;}}}
三、构造方法
ConcurrentHashMap常见的构造方法有四个:
-
无参构造方法
-
指定容量大小的构造方法
-
指定容量大小、负载系数的构造方法
-
指定容量大小、负载系数、并发度的构造方法
// 无参初始化Map<Integer, Integer> map1 = new ConcurrentHashMap<>();// 指定容量大小的初始化Map<Integer, Integer> map2 = new ConcurrentHashMap<>(16);// 指定容量大小、负载系数的初始化Map<Integer, Integer> map3 = new ConcurrentHashMap<>(16, 0.75f);// 指定容量大小、负载系数、并发度的初始化Map<Integer, Integer> map4 = new ConcurrentHashMap<>(16, 0.75f, 1);