com.mxixm.fastboot.weixin.util.CacheMap Maven / Gradle / Ivy
The newest version!
package com.mxixm.fastboot.weixin.util;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 用来存储短暂对象的缓存类,实现Map接口,内部有一个定时器用来清除过期(30秒)的对象。
* 扩展了两个功能
*/
public class CacheMap extends AbstractMap {
// 12个小时
private static final long DEFAULT_TIMEOUT = 24 * 60 * 60 * 1000;
private static final Map cacheNameMap = new ConcurrentHashMap<>();
// 十分钟扫一次缓存
private static final long DEFAULT_CLEAR_PERIOD = 10 * 60 * 1000;
private static TimerTask timerTask = new TimerTask() {
@Override
public void run() {
cacheNameMap.values().forEach(v -> clearTimeoutCache(v));
}
};
// 守护线程timer
private static Timer timer = new Timer(true);
static {
// 清理线程可优化为多个
timer.schedule(timerTask, DEFAULT_CLEAR_PERIOD, DEFAULT_CLEAR_PERIOD);
}
public static Builder builder() {
return new Builder<>();
}
static class CacheEntry implements Entry {
long time;
K key;
V value;
CacheEntry(K key, V value) {
super();
this.key = key;
this.value = value;
this.time = System.currentTimeMillis();
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
return this.value = value;
}
}
public static void clearTimeoutCache(CacheMap map) {
long now = System.currentTimeMillis();
Object[] keys = map.keySet().toArray();
for (Object key : keys) {
CacheEntry entry = (CacheEntry) map.getEntryMap().get(key);
if (now - entry.time >= map.getCacheTimeout()) {
map.remove(key);
}
}
}
/**
* 清理超过限制的缓存
* @param map
*/
public static void clearOverflowCache(CacheMap map) {
int maxSize = map.maxSize;
int realMaxSize = maxSize + maxSize / 4;
if (map.size() > realMaxSize) {
int needRemove = map.size() - maxSize;
TreeSet sortedSet = map.entrySet();
Entry e;
while ((e = sortedSet.pollFirst()) != null && needRemove-- > 0) {
map.remove(e.getKey());
}
}
}
private long cacheTimeout;
private Map entryMap = new ConcurrentHashMap<>();
private String cacheName;
/**
* 在读取的时候是否刷新时间
*/
private boolean refreshOnRead;
/**
* 0的时候是无限,最大空间,当然允许超过最大空间,但是只能超过四分之一的量,这样做是为了保证性能
*/
private int maxSize;
public CacheMap(String cacheName, long timeout, boolean refreshOnRead, int maxSize) {
this.cacheName = cacheName;
this.cacheTimeout = timeout;
this.refreshOnRead = refreshOnRead;
this.maxSize = maxSize;
cacheNameMap.put(cacheName, this);
}
public CacheMap(String cacheName, long timeout, boolean refreshOnRead) {
this(cacheName, timeout, refreshOnRead, 0);
}
public CacheMap(String cacheName, long timeout) {
this(cacheName, timeout, false);
}
public CacheMap(String cacheName) {
this(cacheName, DEFAULT_TIMEOUT);
}
public Map getEntryMap() {
return entryMap;
}
public long getCacheTimeout() {
return cacheTimeout;
}
/**
* remove其实是通过这个来实现的,但是这里功能明显导致删除会失败,结果会内存溢出,所以我重写了remove方法
* 这里的entrySet实现可能是有点问题的,因为返回的是一个新的实例。
* @return dummy
*/
@Override
public TreeSet> entrySet() {
TreeSet> entrySet = new TreeSet<>(Comparator.comparing(kvEntry -> ((CacheEntry)kvEntry).time));
Set> wrapEntrySet = entryMap.entrySet();
for (Entry entry : wrapEntrySet) {
entrySet.add(entry.getValue());
}
return entrySet;
}
@Override
public int size() {
return entryMap.size();
}
@Override
public V remove(Object key) {
Entry entry = this.entryMap.remove(key);
if (entry == null) {
return null;
}
return entry.getValue();
}
@Override
public V get(Object key) {
CacheEntry entry = entryMap.get(key);
if (entry == null) {
return null;
}
if (refreshOnRead) {
entry.time = System.currentTimeMillis();
}
return entry == null ? null : entry.value;
}
@Override
public V put(K key, V value) {
// 如果超量,需要清理
if (maxSize > 0 && this.size() > maxSize + maxSize / 4) {
clearOverflowCache(this);
}
CacheEntry entry = new CacheEntry(key, value);
entryMap.put(key, entry);
return value;
}
public static class Builder {
private long cacheTimeout;
private Map entryMap;
private String cacheName;
private boolean refreshOnRead;
private int maxSize;
Builder() {
}
public CacheMap.Builder cacheTimeout(long cacheTimeout) {
this.cacheTimeout = cacheTimeout;
return this;
}
public CacheMap.Builder cacheName(String cacheName) {
this.cacheName = cacheName;
return this;
}
public CacheMap.Builder refreshOnRead() {
this.refreshOnRead = true;
return this;
}
public CacheMap.Builder maxSize(int maxSize) {
this.maxSize = maxSize;
return this;
}
public CacheMap build() {
return new CacheMap<>(cacheName, cacheTimeout, refreshOnRead, maxSize);
}
public String toString() {
return "com.mxixm.fastboot.weixin.util.CacheMap.CacheMapBuilder(cacheTimeout=" + this.cacheTimeout + ", entryMap=" + this.entryMap + ", cacheName=" + this.cacheName + ", refreshOnRead=" + this.refreshOnRead + ", maxSize=" + this.maxSize + ")";
}
}
public static void main(String[] args) {
CacheMap map = CacheMap.builder().cacheName("test").cacheTimeout(1000).maxSize(5).refreshOnRead().build();
map.put("1", "2");
map.put("2", "3");
map.put("3", "4");
map.put("4", "5");
map.put("5", "6");
map.get("1");
map.put("6", "7");
map.put("7", "8");
map.put("8", "9");
map.put("9", "10");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy