//以默认参数为例initalCapacity=16,loadFactor=0.75,concurrencyLevel=16
public ConcurrentHashMap(int initalCapacity, float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
if (concurrencyLevel > MAX_SEGMENTS)
concurrencyLevel = MAX_SEGMENTS;
int sshift = 0;
int ssize = 1;//segment数组长度
while (ssize < concurrencyLevel) {
++sshift;
ssize <= 1;
}//经过ssize左移4位后,ssize=16,ssift=4
/*segmentShift用于参与散列运算的位数,segmentMask是散列运算的掩码,这里有关的散列函数运算和HashMap有类似之处*/
this.segmentShift = 32 – ssift;//段偏移量segmentShift=28
this.segmentMask = ssize – 1;//段掩码segmentMask=15(1111)
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
int c = initialCapacity / ssize;//c = 1
if (c * ssize < initialCapacity)
++c;
int cap = MIN_SEGMENT_TABLE_CAPACITY;//MIN_SEGMENT_TABLE_CAPACITY=2
while (cap < c)//cap = 2, c = 1,false
cap <<= 1;//cap是segment里HashEntry数组的长度,最小为2
/*创建segments数组和segment[0]*/
Segment<K,V> s0 = new Segment<K,V>(loadFactor, (int)(cap * loadFactor), (HashEntry<K,V>[]) new HashEntry[cap]);//参数意为:负载因子=1,数据容量=(int)(2 * 0.75)=1,总容量=2,故每个Segment的HashEntry总容量为2,实际数据容量为1
Segment<K,V> ss = (Segment<K,V>[])new Segment[ssize];//segments数组大小为16
UNSAFE.putOrderedObject(ss, SBASE, s0);
this.segments = ss;
}
//ConcurrentHashMap#put
public V put(K key, V value) {
Segment<K,V> s;
if (value == null)
throw new NullPointerException();
int hash = hash(key);//根据散列函数,计算出key值的散列值
int j = (hash >>> segmentShift) & segmentMask;//这个操作就是定位Segment的数组下标,jdk1.7之前是segmentFor返回Segment,1.7之后直接就取消了这个方法,直接计算数组下标,然后通过偏移量底层操作获取Segment
if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck
(segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment
s = ensureSegment(j);//通过便宜量定位不到就调用ensureSegment方法定位Segment
return s.put(key, hash, value, false);
}
//Segment#put
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
HashEntry<K,V> node = tryLock() ? null : scanAndLockForPut(key, hash, value);//非阻塞获取锁,获取成功node=null,失败
V oldValue;
try {
HashEntry<K,V>[] tab = table;//Segment对应的HashEntry数组长度
int index = (tab.length - 1) & hash;
HashEntry<K,V> first = entryAt(tab, index);//获取HashEntry数组的第一个值
for (HashEntry<K,V> e = first;;) {
if (e != null) {//HashEntry数组已经存在值
K k;
if ((k = e.key) == key || (e.hash == hash && key.equals(k))) {//key值和hash值都相等,则直接替换旧值
oldValue = e.value;
if (!onlyIfAbsent) {
e.value = value;
++modCount;
}
break;
}
e = e.next;//不是同一个值则继续遍历,直到找到相等的key值或者为null的HashEntry数组元素
}
else {//HashEntry数组中的某个位置元素为null
if (node != null)
node.setNext(first);//将新加入节点(key)的next引用指向HashEntry数组第一个元素
else//已经获取到了Segment锁
node = new HashEntry<K,V>(hash, key, value, first)
int c = count + 1;
if (c > threshold && tab.lenth < MAXIUM_CAPACITY)//插入前先判断是否扩容,ConcurrentHashMap扩容与HashMap不同,ConcurrentHashMap只扩Segment的容量,HashMap则是整个扩容
rehash(node);
else
setEntryAt(tab, index, node);//设置为头节点
++modCount;//总容量
count = c;
oldValue = null;
break;
}
}
} finally {
unlock();
}
return oldValue;
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有