com.dream.system.cache.MemoryCache Maven / Gradle / Ivy
package com.dream.system.cache;
import com.dream.system.config.MappedStatement;
import com.dream.util.common.ObjectUtil;
import com.dream.util.exception.DreamRunTimeException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class MemoryCache implements Cache {
private final int limit;
private final double rate;
private final AtomicBoolean canDelete = new AtomicBoolean(true);
protected Map> tableMap = new ConcurrentHashMap<>(512);
protected Map> indexMap = new ConcurrentHashMap<>();
public MemoryCache() {
this(100, 0.25);
}
public MemoryCache(int limit, double rate) {
if (limit <= 0) {
throw new DreamRunTimeException("参数limit必须大于0");
}
if (rate <= 0 || rate > 1) {
throw new DreamRunTimeException("参数rate介于0-1之间");
}
this.limit = limit;
this.rate = rate;
}
@Override
public void put(MappedStatement mappedStatement, Object value) {
CacheKey uniqueKey = mappedStatement.getUniqueKey();
Set tableSet = mappedStatement.getTableSet();
if (uniqueKey != null && !ObjectUtil.isNull(tableSet)) {
CacheKey methodKey = mappedStatement.getMethodKey();
for (String table : tableSet) {
Set cacheKeySet = tableMap.get(table);
if (cacheKeySet == null) {
synchronized (this) {
cacheKeySet = tableMap.get(table);
if (cacheKeySet == null) {
cacheKeySet = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
tableMap.put(table, cacheKeySet);
}
}
}
cacheKeySet.add(methodKey);
}
Map keyMap = indexMap.get(methodKey);
if (keyMap == null) {
synchronized (this) {
keyMap = indexMap.get(methodKey);
if (keyMap == null) {
keyMap = new ConcurrentHashMap<>(limit);
indexMap.put(methodKey, keyMap);
}
}
} else if (keyMap.size() > limit) {
if (canDelete.compareAndSet(true, false)) {
Map finalMap = keyMap;
Iterator> iterator = finalMap.entrySet().iterator();
while (iterator.hasNext()) {
iterator.next();
double random = Math.random();
if (random <= rate) {
iterator.remove();
}
}
canDelete.set(true);
}
}
keyMap.put(uniqueKey, value);
}
}
@Override
public Object get(MappedStatement mappedStatement) {
CacheKey uniqueKey = mappedStatement.getUniqueKey();
if (uniqueKey != null) {
CacheKey methodKey = mappedStatement.getMethodKey();
Map keyMap = indexMap.get(methodKey);
if (keyMap != null) {
return keyMap.get(uniqueKey);
}
}
return null;
}
@Override
public void remove(MappedStatement mappedStatement) {
Set tableSet = mappedStatement.getTableSet();
if (!ObjectUtil.isNull(tableSet)) {
for (String table : tableSet) {
Set cacheKeySet = tableMap.get(table);
if (!ObjectUtil.isNull(cacheKeySet)) {
for (CacheKey cacheKey : cacheKeySet) {
Map keyMap = indexMap.remove(cacheKey);
if (!ObjectUtil.isNull(keyMap)) {
keyMap.clear();
}
}
cacheKeySet.clear();
}
}
}
}
@Override
public void clear() {
for (Set cacheKeySet : tableMap.values()) {
cacheKeySet.clear();
}
tableMap.clear();
for (Map cacheKeyMap : indexMap.values()) {
cacheKeyMap.clear();
}
indexMap.clear();
}
}