概述
使用java自带的HashMap和ConcurrentHashMap可以做应用程序缓存,但直接使用会导致内存无限增长,产生OOM异常.
解决办法
使用软引用和虚引用
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
|
import java.lang.ref.SoftReference; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap;
public class <K, V> {
private final ConcurrentHashMap<SoftReference<K>, SoftReference<V>> cache = new ConcurrentHashMap<>();
public V get(K k) {
Objects.requireNonNull(k);
SoftReference<K> key = new SoftReference<>(k); SoftReference<V> value = cache.get(key);
return value == null ? null : value.get(); }
public V put(K k, V v) {
Objects.requireNonNull(k); Objects.requireNonNull(v);
SoftReference<K> key = new SoftReference<>(k); SoftReference<V> value = new SoftReference<>(v);
SoftReference<V> oldValue = cache.put(key, value);
return oldValue == null ? null : oldValue.get(); }
public V remove(K k) {
Objects.requireNonNull(k);
SoftReference<K> key = new SoftReference<>(k); SoftReference<V> oldValue = cache.remove(key);
return oldValue == null ? null : oldValue.get(); } }
|
使用LRUMap
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
|
import java.util.LinkedHashMap; import java.util.Map;
public class LRUMap<K, V> extends LinkedHashMap<K, V> {
private final int max;
public LRUMap(int max) { super((int) (max * 1.4f), 0.75f, true); this.max = max; }
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > max; }
public synchronized V getValue(K k) { return get(k); }
public synchronized V putValue(K k, V v) { return put(k, v); }
public synchronized boolean removeValue(K k, V v) { return remove(k, v); } }
|
使用guava cache
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
|
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit;
public class GuavaCacheMap<K, V> {
private LoadingCache<K, V> cache = null;
public GuavaCacheMap() { cacheInit(); }
private void cacheInit() {
cache = CacheBuilder.newBuilder() .maximumSize(100) .expireAfterWrite(30L, TimeUnit.SECONDS) .expireAfterAccess(30L, TimeUnit.SECONDS) .refreshAfterWrite(20L, TimeUnit.SECONDS) .weakKeys() .build(new CacheLoader<K, V>() { public V load(K k) throws Exception { return null; } }); }
public V get(K k) throws ExecutionException {
return cache.get(k); }
public void put(K k, V v) {
cache.put(k, v); } }
|
近期评论