描述
Map线程安全的实现,通过数组+链表实现。关键属性:sizeCtl。
实现流程
-
构造器:调用构造器并不会初始化数组
- 无参构造器:里面啥都没有,空的方法
- 带初始容量构造器:实际初始容量不是是参数值,而是参数值的2倍。通过tableSizeFor得到大于或等于参数值2次幂的值
public LcqConcurrentHashMap(int initCap) { if (initCap < 0) { throw new IllegalArgumentException(); } // 得到的容量大小肯定是传值的2次幂 int cap = initCap >= MAXIMUM_CAPACITY>>>1 ? MAXIMUM_CAPACITY : tableSizeFor(initCap + initCap >> 1 + 1); // sizeCtl为正数,如果没有初始化表示容量,如果已经初始化表示扩容阀值。这里表示容量 this.sizeCtl = cap; } private static final int tableSizeFor(int c) { // 防止整型越界 int n = c - 1; // 保证得到2次幂的值 n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; }
-
put新增元素,循环迭代table(存放节点的数组),直到table不为空或者table长度不为0
- 如果table为空或者table.length为0,则初始化数组。
- while循环判断table是否为空,如果为空并且sizeCtl为-1,表示有其他线程正在初始化,Thread.yield()让出资源让其他线程执行完;
- 如果sizeCtl大于等于0,cas将sc设置为-1(表示正在初始化),初始化节点数组并赋值给table,同事将sizeCtl设置为扩容的阀值,sizeCtl=table.length - table.length >>>2;
- 如果
- 如果table为空或者table.length为0,则初始化数组。
网友评论