一、前言
关于taobao的tddl-common包(5.1.0)的com.taobao.tddl.common.utils.GoogleConcurrentLruCache最近最少使用置换算法,详见源码说明。
二、源码说明
![]() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | package com.taobao.tddl.common.utils; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder; import com.googlecode.concurrentlinkedhashmap.EvictionListener; import com.googlecode.concurrentlinkedhashmap.Weighers; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; public class GoogleConcurrentLruCache<K, V> { private ConcurrentLinkedHashMap<K, V> cache; private static final int DEFAULT_CAPACITY = 389 ; public static final int DEFAULT_CONCURENCY_LEVEL = 64 ; private AtomicLong get; private AtomicLong hit; public GoogleConcurrentLruCache() { this ( 389 ); } public GoogleConcurrentLruCache( int capacity) { this .get = new AtomicLong(0L); this .hit = new AtomicLong(0L); if (capacity <= 0 ) { capacity = 389 ; } this .cache = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(capacity).weigher(Weighers.singleton()).concurrencyLevel( 64 ).build(); } public GoogleConcurrentLruCache( int capacity, EvictionListener<K, V> listener) { this .get = new AtomicLong(0L); this .hit = new AtomicLong(0L); if (capacity <= 0 ) { capacity = 389 ; } this .cache = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(capacity).weigher(Weighers.singleton()).concurrencyLevel( 64 ).listener(listener).build(); } public long capacity() { return this .cache.capacity(); } public boolean isEmpty() { return this .cache.isEmpty(); } public int size() { return this .cache.size(); } public void clear() { this .cache.clear(); } public V get(Object key) { Object v = this .cache.get(key); this .get.addAndGet(1L); if (v != null ) { this .hit.addAndGet(1L); } return v; } public void put(K key, V value) { this .cache.put(key, value); } public boolean putIfAbsent(K key, V value) { return ( this .cache.putIfAbsent(key, value) == null ); } public boolean replace(K key, V old, V value) { return this .cache.replace(key, old, value); } public void remove(K key) { this .cache.remove(key); } public Set<K> keySet() { return this .cache.keySet(); } public Set<K> hotKeySet( int n) { return this .cache.descendingKeySetWithLimit(n); } public boolean containsKey(K key) { return this .cache.containsKey(key); } public String getStatus() { StringBuilder sb = new StringBuilder(); sb.append( "current size:" ); sb.append( this .cache.size()); sb.append( " get:" ); sb.append( this .get); sb.append( " hit:" ); sb.append( this .hit); sb.append( " hit ratio:" ); if ( this .get.longValue() > 0L) { sb.append( this .hit.doubleValue() / this .get.doubleValue() * 100 .0D); sb.append( "%" ); } else { sb.append( "--" ); } this .get.set(0L); this .hit.set(0L); return sb.toString(); } } |