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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
| package top.meethigher.cachestore.cache.impl;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import top.meethigher.cachestore.model.CacheWrapper; import top.meethigher.cachestore.utils.AssertUtil;
import java.util.*; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LruInMemoryCacheStore<K, V> extends AbstractCacheStore<K, V> {
private final Logger log = LoggerFactory.getLogger(LruInMemoryCacheStore.class);
private final Timer timer;
private final long PERIOD = 1000;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock();
private final LruMap cacheMap;
public LruInMemoryCacheStore() { this(1 << 30); }
@SuppressWarnings("all") public LruInMemoryCacheStore(int maxCapacity) { cacheMap = new LruMap(maxCapacity); this.timer = new Timer("lru-cache-expire-cleaner"); timer.scheduleAtFixedRate(new LruInMemoryCacheStore.LruCacheExpireCleaner(), 0, PERIOD); }
@Override public Optional<CacheWrapper<V>> getInternal(K key) { readLock.lock(); try { AssertUtil.notEmpty(key, "[getInternal] Cache key不能为空"); return Optional.ofNullable(cacheMap.get(key)); } finally { readLock.unlock(); } }
@Override public void putInternal(K key, CacheWrapper<V> cacheWrapper) { writeLock.lock(); try { AssertUtil.notEmpty(key, "[putInternal] Cache key不能为空"); cacheMap.put(key, cacheWrapper); } finally { writeLock.unlock(); } }
@Override public boolean putInternalIfAbsent(K key, CacheWrapper<V> cacheWrapper) { AssertUtil.notEmpty(key, "[putInternalIfAbsent] Cache key不能为空"); AssertUtil.notEmpty(cacheWrapper, "[putInternalIfAbsent] Cache value不能为空"); writeLock.lock(); try { Optional<V> valueOptional = get(key); if (valueOptional.isPresent()) { log.info("[putInternalIfAbsent] 缓存中已经存在[{}], 不可重复存储", key); return false; } putInternal(key, cacheWrapper); return true;
} finally { writeLock.unlock(); } }
@Override public void delete(K key) { writeLock.lock(); try { AssertUtil.notEmpty(key, "[delete] Cache key不能为空"); cacheMap.remove(key); } finally { writeLock.unlock(); } }
@Override public LinkedHashMap<K, V> toMap() { readLock.lock(); try { LinkedHashMap<K, V> map = new LinkedHashMap<>(); cacheMap.forEach((k, v) -> { map.put(k, v.getData()); }); return map; } finally { readLock.unlock(); } }
@Override public void clear() { writeLock.lock(); try { cacheMap.clear(); } finally { writeLock.unlock(); } }
private class LruCacheExpireCleaner extends TimerTask { @Override public void run() { writeLock.lock(); try { Set<K> keySet = new HashSet<>(cacheMap.keySet()); for (K key : keySet) { if (!LruInMemoryCacheStore.this.get(key).isPresent()) { log.info("缓存[{}]已过期", key); } } } finally { writeLock.unlock(); }
} }
private class LruMap extends LinkedHashMap<K, CacheWrapper<V>> {
private final int maxCapacity;
public LruMap(int maxCapacity) { this.maxCapacity = maxCapacity; }
@Override protected boolean removeEldestEntry(Map.Entry<K, CacheWrapper<V>> eldest) { log.info("队列中最不常用的数据key {}", eldest.getKey()); return this.size() > maxCapacity; } } }
|