提交 24a7c9ea 编写于 作者: M mxd

修复无法`new HashMap()`的`BUG`

上级 70b2152a
package org.ssssssss.magicapi.modules.db.cache;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 默认SQL缓存实现
*
* @author mxd
*/
public class DefaultSqlCache extends LinkedHashMap<String, DefaultSqlCache.ExpireNode<Object>> implements SqlCache {
private final String separator = ":";
private final int capacity;
public class DefaultSqlCache implements SqlCache {
private final long expire;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final LRUCache cache;
public DefaultSqlCache(int capacity, long expire) {
super((int) Math.ceil(capacity / 0.75) + 1, 0.75f, true);
// 容量
this.capacity = capacity;
// 固定过期时间
this.expire = expire;
this.cache = new LRUCache(capacity, expire);
}
@Override
public void put(String name, String key, Object value) {
// 封装成过期时间节点
put(name, key, value, this.expire);
cache.put(name, key, value);
}
@Override
public void put(String name, String key, Object value, long ttl) {
long expireTime = ttl > 0 ? (System.currentTimeMillis() + ttl) : (this.expire > -1 ? System.currentTimeMillis() + this.expire : Long.MAX_VALUE);
lock.writeLock().lock();
try {
// 封装成过期时间节点
put(name + separator + key, new ExpireNode<>(expireTime, value));
} finally {
lock.writeLock().unlock();
}
cache.put(name, key, value, ttl);
}
@Override
public Object get(String name, String key) {
key = name + separator + key;
lock.readLock().lock();
ExpireNode<Object> expireNode;
try {
expireNode = super.get(key);
} finally {
lock.readLock().unlock();
}
if (expireNode == null) {
return null;
}
// 惰性删除过期的
// if (this.expire > -1L && expireNode.expire < System.currentTimeMillis()) {
if (expireNode.expire < System.currentTimeMillis()) {
try {
lock.writeLock().lock();
super.remove(key);
} finally {
lock.writeLock().unlock();
}
return null;
}
return expireNode.value;
return cache.get(name, key);
}
@Override
public void delete(String name) {
try {
lock.writeLock().lock();
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
String prefix = name + separator;
// 清除所有key前缀为name + separator的缓存
while (iterator.hasNext()) {
Map.Entry<String, ExpireNode<Object>> entry = iterator.next();
if (entry.getKey().startsWith(prefix)) {
iterator.remove();
}
}
} finally {
lock.writeLock().unlock();
}
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, ExpireNode<Object>> eldest) {
if (this.expire > -1L && size() > capacity) {
clean();
}
// lru淘汰
return size() > this.capacity;
}
/**
* 清理已过期的数据
*/
private void clean() {
try {
lock.writeLock().lock();
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
long now = System.currentTimeMillis();
while (iterator.hasNext()) {
Map.Entry<String, ExpireNode<Object>> next = iterator.next();
// 判断是否过期
if (next.getValue().expire < now) {
iterator.remove();
}
}
} finally {
lock.writeLock().unlock();
}
cache.delete(name);
}
/**
* 过期时间节点
*/
static class ExpireNode<V> {
long expire;
V value;
ExpireNode(long expire, V value) {
this.expire = expire;
this.value = value;
}
}
}
package org.ssssssss.magicapi.modules.db.cache;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* LRU缓存实现
*
* @author mxd
*/
public class LRUCache extends LinkedHashMap<String, LRUCache.ExpireNode<Object>> {
private final String separator = ":";
private final int capacity;
private final long expire;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public LRUCache(int capacity, long expire) {
super((int) Math.ceil(capacity / 0.75) + 1, 0.75f, true);
// 容量
this.capacity = capacity;
// 固定过期时间
this.expire = expire;
}
public void put(String name, String key, Object value) {
// 封装成过期时间节点
put(name, key, value, this.expire);
}
public void put(String name, String key, Object value, long ttl) {
long expireTime = ttl > 0 ? (System.currentTimeMillis() + ttl) : (this.expire > -1 ? System.currentTimeMillis() + this.expire : Long.MAX_VALUE);
lock.writeLock().lock();
try {
// 封装成过期时间节点
put(name + separator + key, new ExpireNode<>(expireTime, value));
} finally {
lock.writeLock().unlock();
}
}
public Object get(String name, String key) {
key = name + separator + key;
lock.readLock().lock();
ExpireNode<Object> expireNode;
try {
expireNode = super.get(key);
} finally {
lock.readLock().unlock();
}
if (expireNode == null) {
return null;
}
// 惰性删除过期的
// if (this.expire > -1L && expireNode.expire < System.currentTimeMillis()) {
if (expireNode.expire < System.currentTimeMillis()) {
try {
lock.writeLock().lock();
super.remove(key);
} finally {
lock.writeLock().unlock();
}
return null;
}
return expireNode.value;
}
public void delete(String name) {
try {
lock.writeLock().lock();
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
String prefix = name + separator;
// 清除所有key前缀为name + separator的缓存
while (iterator.hasNext()) {
Map.Entry<String, ExpireNode<Object>> entry = iterator.next();
if (entry.getKey().startsWith(prefix)) {
iterator.remove();
}
}
} finally {
lock.writeLock().unlock();
}
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, ExpireNode<Object>> eldest) {
if (this.expire > -1L && size() > capacity) {
clean();
}
// lru淘汰
return size() > this.capacity;
}
/**
* 清理已过期的数据
*/
private void clean() {
try {
lock.writeLock().lock();
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
long now = System.currentTimeMillis();
while (iterator.hasNext()) {
Map.Entry<String, ExpireNode<Object>> next = iterator.next();
// 判断是否过期
if (next.getValue().expire < now) {
iterator.remove();
}
}
} finally {
lock.writeLock().unlock();
}
}
/**
* 过期时间节点
*/
static class ExpireNode<V> {
long expire;
V value;
ExpireNode(long expire, V value) {
this.expire = expire;
this.value = value;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册