ConcurrentHashMap是线程安全的HashMap的实现
和HashMap一样,同样有initialCapacity和loadFactor属性,多了一个concurrentyLevel属性,在调用构造器的情况下,这三个属性分别为16,0.75,16。
设置了以上三个属性值后,基于以下方式计算size
int sshhift = 0;
int ssize = 1;
while(ssize < concurrentyLevel){
++sshift;
ssize <<=1;
}
在concurrentcyLevel为16的情况下,最终计算出ssize为16,并使用ssize作为参数传入Segment的newArray方法,创建大小为16的对象数组,按照以下算法
int c = initialCapacity/ssize;
if(c * ssize < initialCapacity)
++c;
int cap =1;
while(cap < c)
cap <<=1;;
根据以上参数值,计算出cap为1,最后为Segment对象数组创建Segment对象,传入的参数为cap和loadFactor。Segment对象继承ReentrantLock,在创建Segment对象时其所做的动作为创建指定大小的cap的HashEntry对象数组,并基于数组的大小以及loadFactor计算threshold的值:threshold=(int)(newTable.length*loadFactor);
put操作
ConcurrentHashMap基于concurrentLevel划分出多个Segment来对key-value进行存储,从而避免每次put操作都要锁住整个数组。在默认情况下,最佳情况下可以允许16个线程并发无阻塞的操作集合对象,尽可能地减少并发时的阻塞对象。
关于测试
在单线程下ConcurrentHashMap性能稍逊与HashMap
分布式JAVA应用测试结果多线程:
无论元素量为多少,在线程为10时,CunrrentHashMap带来的性能提升不明显。但在线程为50和100时,ConcurrentHashMap在增加元素和删除元素时带来了一倍左后的性能提升,在查找元素上带来了10倍左右的性能提升,并且随着线程数增长,ConcurrentHashMap性能没有出现下降的现象。