diff --git a/CHANGELOG.md b/CHANGELOG.md index 468ad037b..1c1df9dd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * ### 🐞Bug修复 * 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github) +* 【cache 】 修复WeakCache键值强关联导致的无法回收问题(issue#1953@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java b/hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java index f9dca42a0..dc203cb9c 100644 --- a/hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java +++ b/hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java @@ -17,11 +17,11 @@ public class CacheObj 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; /** * 构造 diff --git a/hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java b/hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java index 3a98bc601..21b2bb16a 100644 --- a/hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java +++ b/hutool-cache/src/main/java/cn/hutool/cache/impl/WeakCache.java @@ -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; * 对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。
* 丢弃某个键时,其条目从映射中有效地移除。
* + * @param 键类型 + * @param 值类型 * @author Looly - * - * @param 键 - * @param 值 - * @author looly * @since 3.0.7 */ -public class WeakCache extends TimedCache{ +public class WeakCache implements Cache { private static final long serialVersionUID = 1L; + TimedCache, 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 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> cacheObjIterator() { + final Iterator, V>> timedIter = timedCache.cacheObjIterator(); + return new Iterator>() { + @Override + public boolean hasNext() { + return timedIter.hasNext(); + } + + @Override + public CacheObj next() { + final CacheObj, V> next = timedIter.next(); + final CacheObj 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 iterator() { + return timedCache.iterator(); + } } diff --git a/hutool-cache/src/test/java/cn/hutool/cache/WeakCacheTest.java b/hutool-cache/src/test/java/cn/hutool/cache/WeakCacheTest.java new file mode 100644 index 000000000..ce7b03dd8 --- /dev/null +++ b/hutool-cache/src/test/java/cn/hutool/cache/WeakCacheTest.java @@ -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 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()); + } +}