Reference
public class Reference {
//1M
private final byte[] data = new byte[2<<19];
protected void finalize() throws Exception{
System.out.println("the reference will be GC");
}
}
LRUCache
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/***
*
* LRU: least recently used, 最近最少使用
*/
public class LRUCache<K, V> {
/**
* 用于记录key值的顺序
*/
private final LinkedList<K> keyList = new LinkedList<>();
/**
* 用户存储数据
*/
private final Map<K, V> cache = new HashMap<>();
/**
* cache 最大容量
*/
private final int capacity;
private final CacheLoader<K, V> cacheLoader;
public LRUCache(int capacity, CacheLoader<K, V> cacheLoader) {
this.capacity = capacity;
this.cacheLoader = cacheLoader;
}
public void put(K key, V value) {
/**
* 当元素数量超过容量时,将最老的数据清除
*
*/
if (keyList.size() >= capacity) {
K k = keyList.removeFirst();
cache.remove(k);
}
/**
* 如果数据已经存在, 则从key的队列中删除
*/
if (keyList.contains(key)) {
keyList.remove(key);
}
/**
* 将key存放至队尾
*/
keyList.addLast(key);
cache.put(key, value);
}
public V get(K key) {
V value;
// 先将key从keyList中删除
boolean remove = keyList.remove(key);
if (!remove) {
// 删除失败,表示当前key不存在
value = cacheLoader.load(key);
this.put(key, value);
} else {
// 如果删除成功,则从cache中返回数据,并将key放入队尾
value = cache.get(key);
keyList.addLast(key);
}
return value;
}
@Override
public String toString() {
return this.keyList.toString();
}
@FunctionalInterface
interface CacheLoader<K, V> {
V load(K k);
}
}
测试
/**
* -Xmx128M 最大堆大小
* -Xms64M 初始化堆大小
* -XX:+PrintGCDetails 在控制台输出GC详细信息
*
* -Xmx128M -Xms64M -XX:+PrintGCDetails
*/
LRUCache<Integer, Reference> cache = new LRUCache<>(200, key -> new Reference());
for (int i = 0; i < Integer.MAX_VALUE; i++) {
cache.get(i);
TimeUnit.SECONDS.sleep(1);
System.out.println(i + " reference stored to cache");
}
SoftLRUCache
package com.james.example.thread.jcp_multithread_architecture.chapter25;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/***
*
* LRU: least recently used, 最近最少使用
*/
public class SoftLRUCache<K, V> {
/**
* 用于记录key值的顺序
*/
private final LinkedList<K> keyList = new LinkedList<>();
/**
* 用户存储数据
* value 采用SoftReference修饰
*/
private final Map<K, SoftReference<V>> cache = new HashMap<>();
/**
* cache 最大容量
*/
private final int capacity;
private final CacheLoader<K, V> cacheLoader;
public SoftLRUCache(int capacity, CacheLoader<K, V> cacheLoader) {
this.capacity = capacity;
this.cacheLoader = cacheLoader;
}
public void put(K key, V value) {
/**
* 当元素数量超过容量时,将最老的数据清除
*
*/
if (keyList.size() >= capacity) {
K k = keyList.removeFirst();
cache.remove(k);
}
/**
* 如果数据已经存在, 则从key的队列中删除
*/
if (keyList.contains(key)) {
keyList.remove(key);
}
/**
* 将key存放至队尾
*/
keyList.addLast(key);
/**
* 保存SoftReference
*/
cache.put(key, new SoftReference<>(value));
}
public V get(K key) {
V value;
// 先将key从keyList中删除
boolean remove = keyList.remove(key);
if (!remove) {
// 删除失败,表示当前key不存在
value = cacheLoader.load(key);
this.put(key, value);
} else {
// 如果删除成功,则从cache中返回数据,并将key放入队尾
value = cache.get(key).get();// 调用SoftReference.get 方法获取
keyList.addLast(key);
}
return value;
}
@Override
public String toString() {
return this.keyList.toString();
}
@FunctionalInterface
interface CacheLoader<K, V> {
V load(K k);
}
}