<< 1];for (int i = 0; i < n; ++i)rs[i] = as[i];counterCells = rs;}} finally {cellsBusy = 0;}collide = false;continue;// Retry with expanded table}// (5)重新生成一个伪随机数赋值给h,进行下一次循环判断// 再哈希h = ThreadLocalRandom.advanceProbe(h);}// 2.as 为null or as是空的else if (cellsBusy == 0 && counterCells == as &&U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {boolean init = false;try {// Initialize table// 多次判断counterCells == as,未防止as变更if (counterCells == as) {// 初始化CounterCell数组,初始容量为2CounterCell[] rs = new CounterCell[2];rs[h & 1] = new CounterCell(x);counterCells = rs;init = true;}} finally {cellsBusy = 0;}if (init)break;}// 3. 2中修改CELLSBUSY失败没抢到初始化as的锁,则尝试 直接cas修改baseCount + xelse if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))break;// Fall back on using base}}
2、
如何统计所有元素个数呢?基数+[]之和 。
final long sumCount() {CounterCell[] as = counterCells; CounterCell a;long sum = baseCount;if (as != null) {for (int i = 0; i < as.length; ++i) {if ((a = as[i]) != null)sum += a.value;}}return sum;}
像提供给用户获取元素个数的方法size()以及判空的()都是调用了() 。
public int size() {long n = sumCount();return ((n < 0L) ? 0 :(n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :(int)n);}public boolean isEmpty() {return sumCount() <= 0L;}
四、扩容
扩容是的核心,明白作者的意图就不觉得难了 。扩容机制的触发有三个地方:
1、触发扩容
除去链表转红黑树可能触发的扩容,算是最正统的扩容源头,所以首先从开始探寻扩容的神秘足迹 。
private final void addCount(long x, int check) {CounterCell[] as; long b, s;// 更新元素个数,详细解析看 三、if ((as = counterCells) != null ||!U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {CounterCell a; long v; int m;boolean uncontended = true;// ThreadLocalRandom.getProbe() 相当于当前线程的hash值if (as == null || (m = as.length - 1) < 0 ||(a = as[ThreadLocalRandom.getProbe() & m]) == null ||!(uncontended =U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {// 找到对应的格子不为null,则cas 该格子内的value+x// counterCells为空or对应格子为空or update格子失败uncontended=false,// 则进入fullAddCount,这个方法是一定会加成功的,但是因为这个过程可能会比较耗时,加成功就立刻退出整个方法了,fullAddCount(x, uncontended);return;}// 从put走到addCount,check是一定>=2的,// 从computeIfAbsent到addCount,可能check =1,意为没有发生哈希冲突的添加元素,则不会检查扩容 。// 毕竟扩容是个耗时的操作if (check <= 1)return;// 统计下元素总个数 。s = sumCount();}// 扩容重点看这里// 替换节点和清空数组时,check=-1,只做元素个数递减,不会触发扩容检查,也不会缩容 。if (check >= 0) {Node
- 中国5个最有特色的摩天轮第四个独一无二第五个世界最高 中国之最摩天轮
- 徐静雨:现役中库里排第二杜兰特只能排第三,这排名非常不严谨 徐静雨各个位置历史之最
- 火影忍者十大瞳术排行榜:轮墓·边狱只能排第二 世界十大瞳术
- 湖二师学子三下乡:素描画中国 中国之最简单画法
- 塞纳当选F1过去四十年最快车手!舒马赫、汉密尔顿分列二三 f1历史之最车手排位
- H5云商城源码全新UI|支持易支付v1.0【个人开发全网首发】
- 二 自动化测试 - RFT系列教程4: RFT是如何识别控件的 对象库与脚本
- 清朝十二帝:揭光绪帝和他的四个男人之谜
- 来涨姿势了,可能有用并使你才识渊博的冷知识来袭 二 跳远的吉尼斯记录
- 七十二景