ehcache3的evict策略是怎样的呢?从put操作可以一窥,这里以单层heap cache为例。

ehcache3的evict策略不可设置,只能通过eviction-advisor建议evict,但这种建议得不到保证且低效。ehcache3的evict策略其实是一种基于样本的LRU算法,即在全量数据中采集一定数量样本(默认为8),在样本集中选取lastAccessTime最小的进行evict。

 1 //put操作先存入元素,然后判断是否进行evict,有删减
 2 public PutStatus put(final K key, final V value) throws StoreAccessException {
 3 
 4   checkKey(key);
 5   checkValue(value);
 6   final long now = timeSource.getTimeMillis();
 7 
 8     //map.compute会进入ConcurrentHashMap遍历元素并计算value
 9   map.compute(key, new BiFunction<K, OnHeapValueHolder<V>, OnHeapValueHolder<V>>() {
10     @Override
11     public OnHeapValueHolder<V> apply(K mappedKey, OnHeapValueHolder<V> mappedValue) {
12 
13       if (mappedValue != null && mappedValue.isExpired(now, TimeUnit.MILLISECONDS)) {
14         updateUsageInBytesIfRequired(- mappedValue.size());
15         mappedValue = null;
16       }
17 
18       if (mappedValue == null) {
19         OnHeapValueHolder<V> newValue = newCreateValueHolder(key, value, now, eventSink);
20         if (newValue != null) {
21           updateUsageInBytesIfRequired(newValue.size());
22           statOutcome.set(StoreOperationOutcomes.PutOutcome.PUT);
23         }
24         return newValue;
25       } else {
26         OnHeapValueHolder<V> newValue = newUpdateValueHolder(key, mappedValue, value, now, eventSink);
27         if (newValue != null) {
28           updateUsageInBytesIfRequired(newValue.size() - mappedValue.size());
29         } else {
30           updateUsageInBytesIfRequired(- mappedValue.size());
31         }
32         statOutcome.set(StoreOperationOutcomes.PutOutcome.REPLACED);
33         return newValue;
34       }
35     }
36   });
37   
38     //enforceCapacity会判断是否进行evict操作。
39   enforceCapacity();
40 
41 }

ConcurrentHashMap的compute操作

  1 public V compute(K key,
  2                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
  3   if (key == null || remappingFunction == null)
  4       throw new NullPointerException();
  5   int h = spread(key.hashCode());
  6   V val = null;
  7   int delta = 0;
  8   int binCount = 0;
  9   for (Node<K,V>[] tab = table;;) {
 10     Node<K,V> f; int n, i, fh;
 11     if (tab == null || (n = tab.length) == 0)
 12         tab = initTable();
 13     else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
 14       Node<K,V> r = new ReservationNode<K,V>();
 15       synchronized (r) {
 16         if (casTabAt(tab, i, null, r)) {
 17           binCount = 1;
 18           Node<K,V> node = null;
 19           try {
 20                 //桶内无元素,计算key的value,如果value非null则添加该key-value(Node);
 21                 //如果value为null则什么也不做
 22             if ((val = remappingFunction.apply(key, null)) != null) {
 23                 delta = 1;
 24                 node = new Node<K,V>(h, key, val, null);
 25             }
 26           } finally {
 27             setTabAt(tab, i, node);
 28           }
 29         }
 30       }
 31       if (binCount != 0)
 32         break;
 33     }
 34     else if ((fh = f.hash) == MOVED)
 35       tab = helpTransfer(tab, f);
 36     else {
 37       synchronized (f) {
 38         if (tabAt(tab, i) == f) {
 39           if (fh >= 0) {
 40             binCount = 1;
 41             for (Node<K,V> e = f, pred = null;; ++binCount) {
 42               K ek;
 43               if (e.hash == h &&
 44                   ((ek = e.key) == key ||
 45                    (ek != null && key.equals(ek)))) {
 46                 //桶内找到与key对应的node,计算value
 47                 val = remappingFunction.apply(key, e.val);
 48                 //如果value非null,则使用计算后的value替换旧的value
 49                 if (val != null)
 50                   e.val = val;
 51                 //如果value为null,则删除该node
 52                 else {
 53                   delta = -1;
 54                   Node<K,V> en = e.next;
 55                   if (pred != null)
 56                     pred.next = en;
 57                   else
 58                     setTabAt(tab, i, en);
 59                 }
 60                 break;
 61               }
 62               pred = e;
 63               //桶内没有找到key对应的node,根据key计算value,
 64               //如果value非null则将该key-value加入桶内,如果value为null则什么都不做
 65               if ((e = e.next) == null) {
 66                 val = remappingFunction.apply(key, null);
 67                 if (val != null) {
 68                   delta = 1;
 69                   pred.next =
 70                       new Node<K,V>(h, key, val, null);
 71                 }
 72                 break;
 73               }
 74             }
 75           }
 76           else if (f instanceof TreeBin) {
 77             binCount = 1;
 78             TreeBin<K,V> t = (TreeBin<K,V>)f;
 79             TreeNode<K,V> r, p;
 80             if ((r = t.root) != null)
 81               p = r.findTreeNode(h, key, null);
 82             else
 83               p = null;
 84             V pv = (p == null) ? null : p.val;
 85             val = remappingFunction.apply(key, pv);
 86             if (val != null) {
 87               if (p != null)
 88                 p.val = val;
 89               else {
 90                 delta = 1;
 91                 t.putTreeVal(h, key, val);
 92               }
 93             }
 94             else if (p != null) {
 95               delta = -1;
 96               if (t.removeTreeNode(p))
 97                 setTabAt(tab, i, untreeify(t.first));
 98             }
 99           }
100           }
101       }
102       if (binCount != 0) {
103         if (binCount >= TREEIFY_THRESHOLD)
104           treeifyBin(tab, i);
105         break;
106       }
107     }
108   }
109   if (delta != 0)
110     addCount((long)delta, binCount);
111   return val;
112 }
View Code

相关文章:

  • 2021-09-10
  • 2022-01-11
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-15
  • 2022-01-10
猜你喜欢
  • 2022-12-23
  • 2021-11-21
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-07
  • 2021-07-29
相关资源
相似解决方案