位置:org.springframework.util
�实现接口:java.util.concurrent.ConcurrentMap
继承类:java.util.AbstractMap
作用:支持空值或空键,并提供高并发下性能良好的键值存储调用
一、效果
ConcurrentReferenceHashMap是自spring3.2后增加的一个同步的软(虚)引用Map。关于软引用(SoftRefrence)和虚引用(WeakRefrence)可以参见另一篇文档:[Java] 垃圾回收机制与引用类型
@Test
public void test1(){
ConcurrentReferenceHashMap map = new ConcurrentReferenceHashMap(16, ConcurrentReferenceHashMap.ReferenceType.WEAK);
map.put("key","val");
System.out.println(map); // 输出:{key=val}
System.gc();
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(map); // 输出:{}
}
二、API
@Nullable
private V put(@Nullable final K key, @Nullable final V value, final boolean overwriteExisting) {
return doTask(key, new Task<V>(TaskOption.RESTRUCTURE_BEFORE, TaskOption.RESIZE) {
@Override
@Nullable
protected V execute(@Nullable Reference<K, V> ref, @Nullable Entry<K, V> entry, @Nullable Entries entries) {
if (entry != null) {
V oldValue = entry.getValue();
if (overwriteExisting) {
entry.setValue(value);
}
return oldValue;
}
Assert.state(entries != null, "No entries segment");
entries.add(value);
return null;
}
});
}
@Override
@Nullable
public V get(@Nullable Object key) {
Entry<K, V> entry = getEntryIfAvailable(key);
return (entry != null ? entry.getValue() : null);
}
@Nullable
private Entry<K, V> getEntryIfAvailable(@Nullable Object key) {
Reference<K, V> ref = getReference(key, Restructure.WHEN_NECESSARY);
return (ref != null ? ref.get() : null);
}
@Nullable
protected final Reference<K, V> getReference(@Nullable Object key, Restructure restructure) {
int hash = getHash(key);
return getSegmentForHash(hash).getReference(key, hash, restructure);
}
@Nullable
public Reference<K, V> getReference(@Nullable Object key, int hash, Restructure restructure) {
if (restructure == Restructure.WHEN_NECESSARY) {
restructureIfNecessary(false);
}
if (this.count == 0) {
return null;
}
// Use a local copy to protect against other threads writing
Reference<K, V>[] references = this.references;
int index = getIndex(hash, references);
Reference<K, V> head = references[index];
return findInChain(head, key, hash);
}
三、总结
ConcurrentReferenceHashMap是基于Segment分段锁实现的,与JDK1.7的ConcurrentHashMap是一样的,与JDK1.8的ConcurrentHashMap是不一样的。
在JDK1.7中,ConcurrentHashMap将哈希表分成许多片段(segments),每个片段(table)都类似于HashMap,它有一个HashEntry数组,数组的每项又是HashEntry组成的链表。每个片段都是Segment类型的。Segment本质上是一个可重入的互斥锁,这样每个片段都有了一个锁,这就是“锁分段”。
在JDK1.8中,ConcurrentHashMap没有用“锁分段”来实现线程安全,而是使用CAS算法和synchronized来确保线程安全,但是底层segment并没有被删除的。
四、补充
无