This commit is contained in:
Looly
2021-11-19 02:38:12 +08:00
parent 0694891f5b
commit 1efa09d8ad
4 changed files with 129 additions and 8 deletions

View File

@@ -23,6 +23,7 @@
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题issue#1942@Github
* 【cache 】 修复WeakCache键值强关联导致的无法回收问题issue#1953@Github
-------------------------------------------------------------------------------------------------------------

View File

@@ -17,11 +17,11 @@ public class CacheObj<K, V> implements Serializable{
protected final V obj;
/** 上次访问时间 */
private volatile long lastAccess;
protected volatile long lastAccess;
/** 访问次数 */
protected AtomicLong accessCount = new AtomicLong();
/** 对象存活时长0表示永久存活*/
private final long ttl;
protected final long ttl;
/**
* 构造

View File

@@ -1,5 +1,10 @@
package cn.hutool.cache.impl;
import cn.hutool.cache.Cache;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.lang.mutable.MutableObj;
import java.util.Iterator;
import java.util.WeakHashMap;
/**
@@ -7,18 +12,112 @@ import java.util.WeakHashMap;
* 对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。<br>
* 丢弃某个键时,其条目从映射中有效地移除。<br>
*
* @param <K> 键类型
* @param <V> 值类型
* @author Looly
*
* @param <K> 键
* @param <V> 值
* @author looly
* @since 3.0.7
*/
public class WeakCache<K, V> extends TimedCache<K, V>{
public class WeakCache<K, V> implements Cache<K, V> {
private static final long serialVersionUID = 1L;
TimedCache<MutableObj<K>, V> timedCache;
/**
* 构造
*
* @param timeout 超时
*/
public WeakCache(long timeout) {
super(timeout, new WeakHashMap<>());
this.timedCache = new TimedCache<>(timeout, new WeakHashMap<>());
}
@Override
public int capacity() {
return timedCache.capacity();
}
@Override
public long timeout() {
return timedCache.timeout();
}
@Override
public void put(K key, V object) {
timedCache.put(new MutableObj<>(key), object);
}
@Override
public void put(K key, V object, long timeout) {
timedCache.put(new MutableObj<>(key), object, timeout);
}
@Override
public V get(K key, boolean isUpdateLastAccess, Func0<V> supplier) {
return timedCache.get(new MutableObj<>(key), isUpdateLastAccess, supplier);
}
@Override
public V get(K key, boolean isUpdateLastAccess) {
return timedCache.get(new MutableObj<>(key), isUpdateLastAccess);
}
@Override
public Iterator<CacheObj<K, V>> cacheObjIterator() {
final Iterator<CacheObj<MutableObj<K>, V>> timedIter = timedCache.cacheObjIterator();
return new Iterator<CacheObj<K, V>>() {
@Override
public boolean hasNext() {
return timedIter.hasNext();
}
@Override
public CacheObj<K, V> next() {
final CacheObj<MutableObj<K>, V> next = timedIter.next();
final CacheObj<K, V> nextNew = new CacheObj<>(next.key.get(), next.obj, next.ttl);
nextNew.lastAccess = next.lastAccess;
nextNew.accessCount = next.accessCount;
return nextNew;
}
};
}
@Override
public int prune() {
return timedCache.prune();
}
@Override
public boolean isFull() {
return timedCache.isFull();
}
@Override
public void remove(K key) {
timedCache.remove(new MutableObj<>(key));
}
@Override
public void clear() {
timedCache.clear();
}
@Override
public int size() {
return timedCache.size();
}
@Override
public boolean isEmpty() {
return timedCache.isEmpty();
}
@Override
public boolean containsKey(K key) {
return timedCache.containsKey(new MutableObj<>(key));
}
@Override
public Iterator<V> iterator() {
return timedCache.iterator();
}
}

View File

@@ -0,0 +1,21 @@
package cn.hutool.cache;
import cn.hutool.cache.impl.WeakCache;
import org.junit.Assert;
import org.junit.Test;
public class WeakCacheTest {
@Test
public void removeTest(){
final WeakCache<String, String> cache = new WeakCache<>(-1);
cache.put("abc", "123");
cache.put("def", "456");
Assert.assertEquals(2, cache.size());
cache.remove("abc");
Assert.assertEquals(1, cache.size());
}
}