public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
int sshift = 0;
int ssize = 1;
//找到一个大于或等于concurrencyLevel 的一个
//2的幂次方数
while (ssize < concurrencyLevel) {
++sshift;
ssize <<= 1;
}
//后面用于取hashcode的高位进行运算
this.segmentShift = 32 - sshift;
this.segmentMask = ssize - 1;
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
//确定HahsEntry数组的长度
int c = initialCapacity / ssize;
//上面除可能造成了“向下取整”,而这里要“向上取整”
//所以进行以下判断进行+1
if (c * ssize < initialCapacity)
++c;
//MIN_SEGMENT_TABLE_CAPACITY 默认为2,
//即HashEntry数组最小长度为2
int cap = MIN_SEGMENT_TABLE_CAPACITY;
//这里同样是找一个大于等于c的一个2的幂次方数
//cap就是HashEntry对象的容量
while (cap < c)
cap <<= 1;
// create segments and segments[0]
//创建一个Segment s0对象存放在Segment数组下标为0的
//位置,便于后面存放元素不用再重新计算HahsEntry
//的容量等属性(原型设计思想)
Segment<K,V> s0 =
new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
(HashEntry<K,V>[])new HashEntry[cap]);
Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
//将s0写入ss数组地址为SBASE的位置(就是下标为0)
UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0]
this.segments = ss;
}
public V put(K key, V value) {
Segment<K,V> s;
//这里说明jdk7的ConcurentHashMap是不能存放空的
if (value == null)
throw new NullPointerException();
//算hashcode 这里基本跟jdk7中HashMap
//hash方法一样
int hash = hash(key);
//这里hash值取高位 & segmentMask(即Segment数组的长度,最后求出存放的对应Segment数组下标的位置)
int j = (hash >>> segmentShift) & segmentMask;
//这里可以理解为取Segment数组第j位置上的值,
//如果为空则调用 ensureSegment(j) 方法
if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck
(segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment
//该方法用于返回一个Segment对象,后面具体分析
s = ensureSegment(j);
return s.put(key, hash, value, false);
}
ensureSegment方法分析
private Segment<K,V> ensureSegment(int k) {
final Segment<K,V>[] ss = this.segments;
//获取存放当前元素在Segment数组下标的位置
long u = (k << SSHIFT) + SBASE; // raw offset
Segment<K,V> seg;
//如果获取Segment数组下标为u的元素,如果为空则取
//ss[0]位置上的元素,获取对应HashEntry的属性,便于
//创建一个HashEntry对象
if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) {
Segment<K,V> proto = ss[0]; // use segment 0 as prototype
//默认HashEntry数组大小
int cap = proto.table.length;
//默认加载因子
float lf = proto.loadFactor;
//存放元素个数上极限
int threshold = (int)(cap * lf);
//创建一个HashEntry对象
HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap];
//再次检查下标为u的位置是否为空,可能并发操作
//有元素进来并创建好了
if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
== null) { // recheck
Segment<K,V> s = new Segment<K,V>(lf, threshold, tab);
//如果为空则利用cas防止并发,将创建好的Segment对象放入下标为u的位置,即只可能有一个线程成功
while ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
== null) {
if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s))
break;
}
}
}
return seg;
}
s.put(key, hash, value, false)方法解析
/**
*key : 存放元素的key
*hash : key对应的hash值
*value : 存放的value
* onlyIfAbsent : 存在相同的key 是否覆盖原值
*/
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
HashEntry<K,V> node = tryLock() ? null :
scanAndLockForPut(key, hash, value);
V oldValue;
try {
HashEntry<K,V>[] tab = table;
int index = (tab.length - 1) & hash;
HashEntry<K,V> first = entryAt(tab, index);
for (HashEntry<K,V> e = first;;) {
if (e != null) {
K k;
if ((k = e.key) == key ||
(e.hash == hash && key.equals(k))) {
oldValue = e.value;
if (!onlyIfAbsent) {
e.value = value;
++modCount;
}
break;
}
e = e.next;
}
else {
if (node != null)
node.setNext(first);
else
node = new HashEntry<K,V>(hash, key, value, first);
int c = count + 1;
if (c > threshold && tab.length < MAXIMUM_CAPACITY)
rehash(node);
else
setEntryAt(tab, index, node);
++modCount;
count = c;
oldValue = null;
break;
}
}
} finally {
unlock();
}
return oldValue;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。