cn.hutool.cache.impl.ReentrantCache Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hutool-all Show documentation
Show all versions of hutool-all Show documentation
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
package cn.hutool.cache.impl;
import cn.hutool.core.collection.CopiedIter;
import java.util.Iterator;
import java.util.concurrent.locks.ReentrantLock;
/**
* 使用{@link ReentrantLock}保护的缓存,读写都使用悲观锁完成,主要避免某些Map无法使用读写锁的问题
* 例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,因此读写必须加互斥锁
*
* @param 键类型
* @param 值类型
* @author looly
* @since 5.7.15
*/
public abstract class ReentrantCache extends AbstractCache {
private static final long serialVersionUID = 1L;
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
// TODO 最优的解决方案是使用Guava的ConcurrentLinkedHashMap,此处使用简化的互斥锁
protected final ReentrantLock lock = new ReentrantLock();
@Override
public void put(K key, V object, long timeout) {
lock.lock();
try {
putWithoutLock(key, object, timeout);
} finally {
lock.unlock();
}
}
@Override
public boolean containsKey(K key) {
return null != getOrRemoveExpired(key, false, false);
}
@Override
public V get(K key, boolean isUpdateLastAccess) {
return getOrRemoveExpired(key, isUpdateLastAccess, true);
}
@Override
public Iterator> cacheObjIterator() {
CopiedIter> copiedIterator;
lock.lock();
try {
copiedIterator = CopiedIter.copyOf(cacheObjIter());
} finally {
lock.unlock();
}
return new CacheObjIterator<>(copiedIterator);
}
@Override
public final int prune() {
lock.lock();
try {
return pruneCache();
} finally {
lock.unlock();
}
}
@Override
public void remove(K key) {
lock.lock();
CacheObj co;
try {
co = removeWithoutLock(key);
} finally {
lock.unlock();
}
if (null != co) {
onRemove(co.key, co.obj);
}
}
@Override
public void clear() {
lock.lock();
try {
cacheMap.clear();
} finally {
lock.unlock();
}
}
@Override
public String toString() {
lock.lock();
try {
return super.toString();
} finally {
lock.unlock();
}
}
/**
* 获得值或清除过期值
* @param key 键
* @param isUpdateLastAccess 是否更新最后访问时间
* @param isUpdateCount 是否更新计数器
* @return 值或null
*/
private V getOrRemoveExpired(final K key, final boolean isUpdateLastAccess, final boolean isUpdateCount) {
CacheObj co;
lock.lock();
try {
co = getWithoutLock(key);
if(null != co && co.isExpired()){
//过期移除
removeWithoutLock(key);
co = null;
}
} finally {
lock.unlock();
}
// 未命中
if (null == co) {
if(isUpdateCount){
missCount.increment();
}
return null;
}
if(isUpdateCount){
hitCount.increment();
}
return co.get(isUpdateLastAccess);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy