1.属性介绍
常量
// 最大容量
private static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认容量
private static final int DEFAULT_CAPACITY = 16;
// 默认加载因子
private static final float LOAD_FACTOR = 0.75f;
// 链表长度树化阈值
static final int TREEIFY_THRESHOLD = 8;
// 树形转链表阈值
static final int UNTREEIFY_THRESHOLD = 6;
// 最小树化容量
static final int MIN_TREEIFY_CAPACITY = 64;
实例属性
// 存储数据的table
transient volatile Node<K,V>[] table;
// 表初始化和调整大小控制。如果为负数,则表正在初始化或调整大小:-1 表示初始化,否则 -(1 + 活动调整大小线程的数量)。否则,当 table 为 null 时,保存要在创建时使用的初始表大小,或者默认为 0。初始化后,保存下一个元素计数值,根据该值调整表的大小
private transient volatile int sizeCtl;
2.构造方法
无参构造
public ConcurrentHashMap() {
}
有参构造
public ConcurrentHashMap(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException();
//
int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
MAXIMUM_CAPACITY :
tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
this.sizeCtl = cap;
}
public ConcurrentHashMap(int initialCapacity, float loadFactor) {
this(initialCapacity, loadFactor, 1);
}
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
// 当前初始化容量小于初始化并发级别,则直接将初始化容量赋值为并发级别
if (initialCapacity < concurrencyLevel)
initialCapacity = concurrencyLevel;
// 根据初始化容量和初始化加载因子来计算当前容量
long size = (long)(1.0 + (long)initialCapacity / loadFactor);
// 取比size大的最小2次幂
int cap = (size >= (long)MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY : tableSizeFor((int)size);
// 设置为当前初始化的容量
this.sizeCtl = cap;
}
2.1 tableSizeFor()
private static final int tableSizeFor(int c) {
// 通过位运算计算得到比c大的最小2次幂
int n = c - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
3.put()
public V put(K key, V value) {
return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
// put的ket、value不能为null
if (key == null || value == null) throw new NullPointerException();
// 扰动处理,减少hash冲突概率
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
// 详见3.1 initTable()
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { // 当前下标i对应元素值为null
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // cas,新增节点存储到对应tab[i]中
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) { // tab[i]头节点加锁
if (tabAt(tab, i) == f) { // 判断tab[i]头节点是否改变
if (fh >= 0) { // f.hash值大于等于0代表当前节点是可操作的,树根节点的hash值是-2
binCount = 1;
for (Node<K,V> e = f;; ++binCount) { // 遍历f节点
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) { // 匹配hash、key值,若相等直接覆盖原value,并返回原value
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) { // 遍历完f节点,仍没有匹配key、hash值则创建新节点(尾插法)
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) { // 当前节点为树节点
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}
}
if (binCount != 0) {
// 判断当前链表长度是否大于树化阈值
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
if (oldVal != null)
return oldVal;
break;
}
}
}
addCount(1L, binCount); // 计数
return null;
}
3.1 initTable()
初始化table
private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) { // 若当前table未初始化,进入循环
if ((sc = sizeCtl) < 0) // sizeCtl<0 代表在初始化或调整大小
Thread.yield(); // 让出cpu调度时间
else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { // CAS 将sizeCtl修改为-1,表示当前table正在初始化
try {
if ((tab = table) == null || tab.length == 0) { // 双重锁检查
int n = (sc > 0) ? sc : DEFAULT_CAPACITY; // sc大于0表示,初始化了容量直接使用该容量,反之则使用默认容量16
@SuppressWarnings("unchecked")
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt; // 初始化table
sc = n - (n >>> 2); // sc保存当前扩容阈值,即为0.75x当前容量
}
} finally {
sizeCtl = sc;
}
break;
}
}
return tab;
}
4.get()
public V get(Object key) {
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
int h = spread(key.hashCode()); //扰动函数计算hash值
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) { // 判断table是否相等,tab[i]是否为空
if ((eh = e.hash) == h) {
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
return e.val;
}
else if (eh < 0) // 当前在初始化或调整大小
return (p = e.find(h, key)) != null ? p.val : null;
while ((e = e.next) != null) {
if (e.hash == h &&
((ek = e.key) == key || (ek != null && key.equals(ek))))
return e.val;
}
}
return null;
}
Node<K,V> find(int h, Object k) {
Node<K,V> e = this;
// 遍历e节点比较hash、key
if (k != null) {
do {
K ek;
if (e.hash == h &&
((ek = e.key) == k || (ek != null && k.equals(ek))))
return e;
} while ((e = e.next) != null);
}
return null;
}
版权声明:本文为qq_40790991原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。