https://www.cnblogs.com/zerotomax/p/8687425.html#go0
https://www.cnblogs.com/banjinbaijiu/p/9147434.html
19.1 基础
其底层数据与HashMap的数据结构相同 。ConcurrentHashMap使用的分段锁技术。将ConcurrentHashMap容器的数据分段存储,每一段数据分配一个Segment(锁),当线程占用其中一个Segment时,其他线程可正常访问
19.1.1内部类
说明:可以看到,ConcurrentHashMap的内部类非常的庞大,第二个图是在JDK1.8下增加的类,下面对其中主要的内部类进行分析和讲解。
- Node类
Node类主要用于存储具体键值对,其子类有ForwardingNode、ReservationNode、TreeNode和TreeBin四个子类。四个子类具体的代码在之后的具体例子中进行分析讲解。
- Traverser类
Traverser类主要用于遍历操作,其子类有BaseIterator、KeySpliterator、ValueSpliterator、EntrySpliterator四个类,BaseIterator用于遍历操作。KeySplitertor、ValueSpliterator、EntrySpliterator
则用于键、值、键值对的划分。
- CollectionView类
CollectionView抽象类主要定义了视图操作,其子类KeySetView、ValueSetView、EntrySetView分别表示键视图、值视图、键值对视图。对视图均可以进行操作。
- Segment类
Segment类在JDK1.8中与之前的版本的JDK作用存在很大的差别,JDK1.8下,其在普通的ConcurrentHashMap操作中已经没有失效,其在序列化与反序列化的时候会发挥作用。
- CounterCell
CounterCell类主要用于对baseCount的计数。
19.1.2 成员
implements ConcurrentMap
private static final long serialVersionUID = 7249069246763182397L;
// 表的最大容量
private static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认表的大小
private static final int DEFAULT_CAPACITY = 16;
// 最大数组大小
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 默认并发数
private static final int DEFAULT_CONCURRENCY_LEVEL = 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;
// 每次进行转移的最小值
private static final int MIN_TRANSFER_STRIDE = 16;
// 生成sizeCtl所使用的bit位数
private static int RESIZE_STAMP_BITS = 16;
// 进行扩容所允许的最大线程数
private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
// 记录sizeCtl中的大小所需要进行的偏移位数
private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;
// 一系列的标识
static final int MOVED = -1; // hash for forwarding nodes
static final int TREEBIN = -2; // hash for roots of trees
static final int RESERVED = -3; // hash for transient reservations
static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash
//
/ Number of CPUS, to place bounds on some sizings */
// 获取可用的CPU个数
static final int NCPU = Runtime.getRuntime().availableProcessors();
//
/ For serialization compatibility. */
// 进行序列化的属性
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField(“segments”, Segment[].class),
new ObjectStreamField(“segmentMask”, Integer.TYPE),
new ObjectStreamField(“segmentShift”, Integer.TYPE)
};
// 表
transient volatile Node
// 下一个表
private transient volatile Node
// 基本计数<br /> private transient volatile long baseCount;<br /> //<br /> // 对表初始化和扩容控制<br /> /**<br /> * 用来控制表初始化和扩容的,默认值为0,当在初始化的时候指定了大小,这会将这个大小保存在sizeCtl中,大小为数组的0.75<br /> * 当为负的时候,说明表正在初始化或扩张,<br /> * -1表示初始化<br /> * -(1+n) n:表示活动的扩张线程<br /> */<br /> <br /> private transient volatile int sizeCtl;<br />
// 扩容下另一个表的索引<br /> private transient volatile int transferIndex;
// 旋转锁<br /> private transient volatile int cellsBusy;
// counterCell表<br /> private transient volatile CounterCell[] counterCells;
// views<br /> // 视图<br /> private transient KeySetView<K,V> keySet;<br /> private transient ValuesView<K,V> values;<br /> private transient EntrySetView<K,V> entrySet;<br /> <br /> // Unsafe mechanics<br /> private static final sun.misc.Unsafe U;<br /> private static final long SIZECTL;<br /> private static final long TRANSFERINDEX;<br /> private static final long BASECOUNT;<br /> private static final long CELLSBUSY;<br /> private static final long CELLVALUE;<br /> private static final long ABASE;<br /> private static final int ASHIFT;
static {<br /> try {<br /> U = sun.misc.Unsafe.getUnsafe();<br /> Class<?> k = ConcurrentHashMap.class;<br /> SIZECTL = U.objectFieldOffset<br /> (k.getDeclaredField("sizeCtl"));<br /> TRANSFERINDEX = U.objectFieldOffset<br /> (k.getDeclaredField("transferIndex"));<br /> BASECOUNT = U.objectFieldOffset<br /> (k.getDeclaredField("baseCount"));<br /> CELLSBUSY = U.objectFieldOffset<br /> (k.getDeclaredField("cellsBusy"));<br /> Class<?> ck = CounterCell.class;<br /> CELLVALUE = U.objectFieldOffset<br /> (ck.getDeclaredField("value"));<br /> Class<?> ak = Node[].class;<br /> ABASE = U.arrayBaseOffset(ak);<br /> int scale = U.arrayIndexScale(ak);<br /> if ((scale & (scale - 1)) != 0)<br /> throw new Error("data type scale not a power of two");<br /> ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);<br /> } catch (Exception e) {<br /> throw new Error(e);<br /> }<br /> }<br />}<br /> <br />说明:ConcurrentHashMap的属性很多,其中不少属性在HashMap中就已经介绍过,而对于**ConcurrentHashMap而言,添加了Unsafe实例,主要用于反射获取对象相应的字段。**
19.1.3构造函数
对于构造函数而言,会根据输入的initialCapacity的大小来确定一个最小的且大于等于initialCapacity大小的2的n次幂,如initialCapacity为15,则sizeCtl为16,若initialCapacity为16,则sizeCtl为
16。若initialCapacity大小超过了允许的最大值,则sizeCtl为最大值。值得注意的是,构造函数中的concurrencyLevel参数已经在JDK1.8中的意义发生了很大的变化,其并不代表所允许的并发数,
其只是用来确定sizeCtl大小,在JDK1.8中的并发控制都是针对具体的桶而言,即有多少个桶就可以允许多少个并发数