ConcurrentHashMap-属性解释

news/2024/7/7 19:07:03 标签: java, hashmap, concurrentHash, 并发扩容, 红黑树

ConcurrentHashMap-属性解释

代表hashmap最大能存这么多个键值对
高两位目的是为了控制?知道的评论区说下

java">private static final int MAXIMUM_CAPACITY = 1 << 30;

代表hashmap默认容量

java">private static final int DEFAULT_CAPACITY = 16;

数组的最大长度

java">static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

默认的并行度,为了兼容jdk1.7版本的Segment

java">private static final int DEFAULT_CONCURRENCY_LEVEL = 16

扩容因子,当元素个数达到0.75*数组长度的时候触发扩容,也是jdk1.7使用,jdk1.8直接使用位操作计算出扩容阈值

java">private static final float LOAD_FACTOR = 0.75f;

树化阈值,当链表长度达到8的时候树化成红黑树,细致来说是这样
当链表长度达到8并且数组长度<64此时只会扩容,
当链表长度达到8并且数组长度>=64才会树化成红黑树

java">static final int TREEIFY_THRESHOLD = 8;

这个64就是上面的64

java">static final int MIN_TREEIFY_CAPACITY = 64;

链化阈值,当红黑树元素个数<=6时退化成链表

java">static final int UNTREEIFY_THRESHOLD = 6;

并发扩容时每个线程最少处理16个桶

java">private static final int MIN_TRANSFER_STRIDE = 16;

这三个常量控制并发扩容的结束,其实就是开始扩容的时候设置sizeCtl成一个负数,每次加入一个线程去扩容就sizeCtl++,每次一个线程扩容结束就sizeCtl–, 那么当所有线程扩容结束后sizeCtl就等于最开始设置的那个负数

java">private static int RESIZE_STAMP_BITS = 16;
private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;

标识为Forwarding节点(hash=-1),当扩容的时候发现桶为null时,会casTab(fwd,i)
当其他线程去执行put操作时,发现定位到的桶是fwd时,就会加入扩容大军,帮助扩容

java">static final int MOVED     = -1;

标识桶为红黑树(hash=-2)

java">static final int TREEBIN   = -2;

标识为ReservationNode节点(hash=-3),用于map.compute操作

java">static final int RESERVED  = -3; 

我解释一下该节点,map.put操作如下
在这里插入图片描述map.compute(“e”,(x,y)->x+" compute "+y); 如下
在这里插入图片描述
为什么他要加sync锁呢?知道的评论区说下

设想如果没有ReservationNode节点,就没办法使用锁,他就只能写类似下面的代码,而apply方法是非线程安全的,多线程同时compute进来的话会导致不安全

java">if ((val = remappingFunction.apply(key, null)) != null) {
	node = new Node<K,V>(h, key, val, null);
	casTabAt(tab, i, null, node)
}

普通链表节点,hash为正数

java">static final int HASH_BITS = 0x7fffffff; 

cpu核心数

java">static final int NCPU = Runtime.getRuntime().availableProcessors();

hash桶

java">transient volatile Node<K,V>[] table;

扩容时产生的新数组=2倍大小table

java">private transient volatile Node<K,V>[] nextTable;

建议去看我的博客 LongAdder

java">private transient volatile long baseCount;
private transient volatile int cellsBusy;
private transient volatile CounterCell[] counterCells;

这个举例吧,涉及到并发扩容的东西了

java">private transient volatile int transferIndex;

如图,transferIndex表示当前线程应该迁移桶的最大下标+1
比如线程1应该迁移桶3,桶2,那么transferIndex=4
线程1应该迁移桶1,桶0,那么transferIndex=2
在这里插入图片描述

java">private transient volatile int sizeCtl;

1:如果使用带参initCapacity构造器,sizeCtl就是计算出来的容量
在这里插入图片描述
2:初始化table时取值-1
在这里插入图片描述
3:初始化完成设置为0.75*n,扩容阈值

4:第一条线程扩容设置成一个负数,一定是负数

java">U.compareAndSwapInt(this, SIZECTL, sc, (rs << RESIZE_STAMP_SHIFT) + 2)

5:后续每加入一个扩容线程sizeCtl++

java">U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)

6:后续每个扩容线程结束sizeCtl–

java">U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)

http://www.niftyadmin.cn/n/1037391.html

相关文章

map的使用

map&#xff0c;我们一般称为字典或是映射&#xff0c;它提供了一对一的映射关系 使用场景 : map用于查找问题中某个元素出现的次数&#xff0c;比如问‘a’这个元素在数组中出现了多少次。这个只是最基本的应用场景&#xff0c;由于可以有任意的键值对的对应&#xff0c;map的…

ConcurrentHashMap-put

ConcurrentHashMap-put 推荐先读&#xff1a;ConcurrentHashMap属性解释 putVal主流程 initTable初始化table分支流程 helpTransfer帮助扩容分支流程 putVal主流程锁住桶后&#xff0c;链表插入/更新 putVal主流程锁住桶后&#xff0c;红黑树插入/更新 putVal主流程ad…

java变量使用,基础类型使用

先来了解java的基础比较常用的几种基础数据类型 int 整数类型 如 10 20 30 String 字符串类型 如 “你好” double 小数点类型 如 99.99 boolean 只有两个值 true 或 false true代表真 false代表假 定义变量的方法 为 类型 变量名 值 例如 int min 13; 这里我们定义了 一个…

排列问题

回溯法首先能处理一种排列问题&#xff0c;即全排列 题目 给定一个没有重复数字的序列&#xff0c;返回其所有可能的全排列。 示例: 输入: 3 1 2 3 输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 有一个递归公式&#xff1a;perm(nums[0…n-1]) {取出一个数字} perm(nums[0……

缓存双写一致性

缓存双写一致性对于读&#xff1a;先读缓存&#xff0c;缓存没有&#xff0c;再读ku&#xff0c;回写缓存&#xff0c;这种没啥说的。对于写&#xff1a;先写库&#xff0c;再删除缓存&#xff0c;本文主要基于这种来探讨一下这样处理有什么问题&#xff1f; 如下图所示&#…

uni-app复选框checkbox大小调整

写vue的朋友就会被经典的误导 这个用样式去调显然解决不了问题 需要transform: scale() 个人建议 0.7大小比较合适 参考代码如下 <checkboxstyle"transform: scale(0.7)":checked"item.isChecked":value"item.isChecked"class"more&quo…

组合问题

回溯法能解决的另一个重要的问题就是组合问题 题目 给定两个整数 n 和 k&#xff0c;返回 1 … n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: 2 4 3 4 2 3 1 2 1 3 1 4 #include <iostream> #include <vector> using namespace std; int n,k; /…

uni-app 修改复选框checkbox选中后背景和字体颜色

用几行css代码就能搞定 不过一定要写在跟节点 App.vue文件中 否则无效 uni-checkbox .uni-checkbox-input {border-radius: 50%;border: 1rpx solid rgb(149, 149, 151); }uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked {border: 1rpx solid rgb(33, 177, 255…