您可以通过创造性地使用线程本地存储来使其工作:
class LRUCacheLHM<K,V> extends LinkedHashMap<K,V> {
private int capacity;
public LRUCacheLHM(int capacity) {
//1 extra element as add happens before remove (101), and load factor big
//enough to avoid triggering resize. True = keep in access order.
super(capacity + 1, 1.1f, true);
this.capacity = capacity;
}
private ThreadLocal<Map.Entry<K,V>> removed = new ThreadLocal<Map.Entry<K,V>>();
private ThreadLocal<Boolean> report = new ThreadLocal<Boolean>();
{
report.set(false);
}
@Override
public boolean removeEldestEntry(Map.Entry<K,V> eldest) {
boolean res = size() > capacity;
if (res && report.get()) {
removed.set(eldest);
}
return res;
}
public Map.Entry<K,V> place(K k, V v) {
report.set(true);
put(k, v);
try {
return removed.get();
} finally {
removed.set(null);
report.set(false);
}
}
}
演示。
该方法背后的想法是通过将线程本地标志设置place(K,V)
为来removeEldestEntry
表示我们希望获得最旧的条目。当看到这个标志并且知道一个条目正在被删除时,它会将最旧的条目放在变量中,这也是线程局部的。report
true
removeEldestEntry
report
调用removeEldestEntry
发生在对put
方法的调用内部。之后,最老的条目是null
, 或 位于report
变量中,准备好被收获。
调用set(null)
对于removed
避免挥之不去的内存泄漏很重要。