首先常用三种HashMap包括HashMap,HashTable和CocurrentHashMap:
变量名称 | 描述 |
---|---|
cocurrencyLevel | 能够满足的并发访问数量,即最多同时可以有多少线程同时访问一个CocurrencyHashMap对象(个人的理解) |
ssize | segments数组的长度(因为要利用位运算和hash算法获取索引,故必须是 2n ),而且在确定长度时能够保证复杂度在 O(logn2) |
segmentShift | 散列后的32中的高位表示segments的索引,代表作无符号右移的偏移量 |
segmentMask | 对应与segment的ssize-1,有效的二进制位都为1,可以通过与散列后的数值与运算得到segment的索引 |
threshold | 一个segment的容量 |
initialCapacity | CocurrentHashMap的初始化容量 |
cap | 一个segment中HashEntry数组的长度 |
loadFactor | 负载因子,我理解的是负载因子越大会导致出现冲突的概率增大,设置的过小又会浪费空间,所以应该根据实际情况考虑空间和时间上的平衡 |
if ( cocurrencyLevel > MAX_SEGMENTS )
cocurrencyLevel = MAX_SEGMENTS;
//如果cocurrencyLevel大于上限,那么取值为上限,
//上限定义为65535,决定了重入锁的segments的数目
int sshift = 0;
int ssize = 1;
//找到大于等于concurrencyLevel的最小的2^n作为segments的大小
while ( ssize < concurrencyLevel ){
++sshift;//记录偏移量,为了以后通过与运算获取segment的索引
ssize <<=1;
}
segmentShift = 32 - sshift;//说明只有高sshift位作为segment的索引
segmentMask = ssize - 1;//能直接通过与运算获取segment的索引
this.segments = Segment.newArray(ssize);
//静态工厂方法构造ssize大小的segment数组
if ( initialCapacity > MAXIMUM_CAPACITY )
initialCapacity = MAXIMUM_CAPACITY;
int c = initCapacity / ssize;
//整个cocurrentHashMap的容量由所有的segment均摊
if ( c * ssize < initCapacity )
++c;
int cap = 1;//segment中的hashEntry数组的长度
while ( cap < c )
cap <<= 1;
//设置loadFactor,保证散列的高效性的同时也保证空间浪费相对有限
for ( int i = 0 ; i < this.segments.length ; i++ )
this.segments[i] = new Segments(cap , loadFactor);
//最终计算出segment的容量threshold=(int)cap*loadFactor;
final Segment segmentFor ( int hash ){
//首先根据segmentShift无符号右移,得到表示segment所以的高位,
//然后与掩码逻辑与得到segment的索引,定位到segment
return segments[(hash>>>segmentShift)&segmentMask];
}
synchronized(其实感觉是可以被重入锁和Condition完全取代的)和volatile的取舍: