位置:org.springframework.util
�实现接口:java.util.concurrent.ConcurrentMap
继承类:java.util.AbstractMap
作用:支持空值或空键,并提供高并发下性能良好的键值存储调用

一、效果

ConcurrentReferenceHashMap是自spring3.2后增加的一个同步的软(虚)引用Map。关于软引用(SoftRefrence)和虚引用(WeakRefrence)可以参见另一篇文档:[Java] 垃圾回收机制与引用类型

  1. @Test
  2. public void test1(){
  3. ConcurrentReferenceHashMap map = new ConcurrentReferenceHashMap(16, ConcurrentReferenceHashMap.ReferenceType.WEAK);
  4. map.put("key","val");
  5. System.out.println(map); // 输出:{key=val}
  6. System.gc();
  7. try {
  8. Thread.currentThread().sleep(5000);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. System.out.println(map); // 输出:{}
  13. }

二、API

  1. @Nullable
  2. private V put(@Nullable final K key, @Nullable final V value, final boolean overwriteExisting) {
  3. return doTask(key, new Task<V>(TaskOption.RESTRUCTURE_BEFORE, TaskOption.RESIZE) {
  4. @Override
  5. @Nullable
  6. protected V execute(@Nullable Reference<K, V> ref, @Nullable Entry<K, V> entry, @Nullable Entries entries) {
  7. if (entry != null) {
  8. V oldValue = entry.getValue();
  9. if (overwriteExisting) {
  10. entry.setValue(value);
  11. }
  12. return oldValue;
  13. }
  14. Assert.state(entries != null, "No entries segment");
  15. entries.add(value);
  16. return null;
  17. }
  18. });
  19. }
  20. @Override
  21. @Nullable
  22. public V get(@Nullable Object key) {
  23. Entry<K, V> entry = getEntryIfAvailable(key);
  24. return (entry != null ? entry.getValue() : null);
  25. }
  26. @Nullable
  27. private Entry<K, V> getEntryIfAvailable(@Nullable Object key) {
  28. Reference<K, V> ref = getReference(key, Restructure.WHEN_NECESSARY);
  29. return (ref != null ? ref.get() : null);
  30. }
  31. @Nullable
  32. protected final Reference<K, V> getReference(@Nullable Object key, Restructure restructure) {
  33. int hash = getHash(key);
  34. return getSegmentForHash(hash).getReference(key, hash, restructure);
  35. }
  36. @Nullable
  37. public Reference<K, V> getReference(@Nullable Object key, int hash, Restructure restructure) {
  38. if (restructure == Restructure.WHEN_NECESSARY) {
  39. restructureIfNecessary(false);
  40. }
  41. if (this.count == 0) {
  42. return null;
  43. }
  44. // Use a local copy to protect against other threads writing
  45. Reference<K, V>[] references = this.references;
  46. int index = getIndex(hash, references);
  47. Reference<K, V> head = references[index];
  48. return findInChain(head, key, hash);
  49. }

三、总结

ConcurrentReferenceHashMap是基于Segment分段锁实现的,与JDK1.7的ConcurrentHashMap是一样的,与JDK1.8的ConcurrentHashMap是不一样的。

在JDK1.7中,ConcurrentHashMap将哈希表分成许多片段(segments),每个片段(table)都类似于HashMap,它有一个HashEntry数组,数组的每项又是HashEntry组成的链表。每个片段都是Segment类型的。Segment本质上是一个可重入的互斥锁,这样每个片段都有了一个锁,这就是“锁分段”。
在JDK1.8中,ConcurrentHashMap没有用“锁分段”来实现线程安全,而是使用CAS算法synchronized来确保线程安全,但是底层segment并没有被删除的。

四、补充


参考资料: Spring—ConcurrentReferenceHashMap