mirror of
https://github.com/LamGC/ContentGrabbingJi.git
synced 2025-04-30 06:37:36 +00:00
[Add] 增加自动清理机制;
[Add] AutoCleanTimer, Cleanable 增加定时清理器和所需实现的接口; [Update] HashCacheStore 实现了 Cleanable 接口, 并使用了一种简单但效率较低的遍历清除方法, 有待改进;
This commit is contained in:
parent
565049f393
commit
d650f12626
@ -0,0 +1,85 @@
|
|||||||
|
package net.lamgc.cgj.bot.cache.local;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时清理机制.
|
||||||
|
* <p>定时通知已实现 {@link Cleanable} 接口的对象进行清理.
|
||||||
|
* @see Cleanable
|
||||||
|
* @author LamGC
|
||||||
|
*/
|
||||||
|
public class AutoCleanTimer implements Runnable {
|
||||||
|
|
||||||
|
private final static Set<Cleanable> CLEANABLE_STORE_SET = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
|
private final static ScheduledExecutorService SCHEDULED_EXECUTOR =
|
||||||
|
new ScheduledThreadPoolExecutor(1,
|
||||||
|
new ThreadFactoryBuilder()
|
||||||
|
.setDaemon(true)
|
||||||
|
.setNameFormat("Thread-AutoClean-%d")
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
private final static Logger log = LoggerFactory.getLogger(AutoCleanTimer.class);
|
||||||
|
|
||||||
|
private final static AtomicBoolean DEBUG_ENABLE = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
static {
|
||||||
|
SCHEDULED_EXECUTOR.scheduleAtFixedRate(new AutoCleanTimer(), 100L, 100L, TimeUnit.MILLISECONDS);
|
||||||
|
Thread shutdownHook = new Thread(SCHEDULED_EXECUTOR::shutdown);
|
||||||
|
shutdownHook.setName("ShutdownThread-AutoClean");
|
||||||
|
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用调试模式.
|
||||||
|
* <p>启用后将会打印相关日志.
|
||||||
|
* @param enable 是否启用调试模式.
|
||||||
|
*/
|
||||||
|
public static void setDebugEnable(boolean enable) {
|
||||||
|
DEBUG_ENABLE.set(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加需要定时执行清理的缓存库
|
||||||
|
* @param store 已实现Cleanable的对象
|
||||||
|
*/
|
||||||
|
public static void add(Cleanable store) {
|
||||||
|
CLEANABLE_STORE_SET.add(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除已添加的缓存库
|
||||||
|
* @param store 需要从AutoCleanTimer移除的对象
|
||||||
|
*/
|
||||||
|
public static void remove(Cleanable store) {
|
||||||
|
CLEANABLE_STORE_SET.remove(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AutoCleanTimer() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (CLEANABLE_STORE_SET.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLEANABLE_STORE_SET.forEach(cleanable -> {
|
||||||
|
try {
|
||||||
|
cleanable.clean();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("{} 执行清理动作时发生异常:\n{}", cleanable.toString(), Throwables.getStackTraceAsString(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
16
ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/Cleanable.java
vendored
Normal file
16
ContentGrabbingJi-CacheStore-local/src/main/java/net/lamgc/cgj/bot/cache/local/Cleanable.java
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package net.lamgc.cgj.bot.cache.local;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可清理接口, 实现该接口代表该类具有清理动作.
|
||||||
|
* @author LamGC
|
||||||
|
*/
|
||||||
|
public interface Cleanable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该方法需要CacheStore完成对过期Entry的清除.
|
||||||
|
* @return 返回已清理数量.
|
||||||
|
* @throws Exception 即使该方法抛出异常, 也不会影响后续情况.
|
||||||
|
*/
|
||||||
|
long clean() throws Exception;
|
||||||
|
|
||||||
|
}
|
@ -20,6 +20,7 @@ package net.lamgc.cgj.bot.cache.local;
|
|||||||
import net.lamgc.cgj.bot.cache.CacheStore;
|
import net.lamgc.cgj.bot.cache.CacheStore;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于 {@link Hashtable} 的缓存存储容器.
|
* 基于 {@link Hashtable} 的缓存存储容器.
|
||||||
@ -28,7 +29,7 @@ import java.util.*;
|
|||||||
* @see net.lamgc.cgj.bot.cache.CacheStore
|
* @see net.lamgc.cgj.bot.cache.CacheStore
|
||||||
* @see Hashtable
|
* @see Hashtable
|
||||||
*/
|
*/
|
||||||
public abstract class HashCacheStore<V> implements CacheStore<V> {
|
public abstract class HashCacheStore<V> implements CacheStore<V>, Cleanable {
|
||||||
|
|
||||||
private final Map<String, CacheItem<V>> cacheMap = new Hashtable<>();
|
private final Map<String, CacheItem<V>> cacheMap = new Hashtable<>();
|
||||||
|
|
||||||
@ -100,6 +101,22 @@ public abstract class HashCacheStore<V> implements CacheStore<V> {
|
|||||||
return Collections.unmodifiableSet(cacheMap.keySet());
|
return Collections.unmodifiableSet(cacheMap.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long clean() {
|
||||||
|
Map<String, CacheItem<V>> cacheMap = getCacheMap();
|
||||||
|
Date currentDate = new Date();
|
||||||
|
AtomicLong cleanCount = new AtomicLong(0);
|
||||||
|
cacheMap.keySet().removeIf(key -> {
|
||||||
|
CacheItem<V> item = cacheMap.get(key);
|
||||||
|
if (item != null && item.isExpire(currentDate)) {
|
||||||
|
cleanCount.incrementAndGet();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return cleanCount.get();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存项.
|
* 缓存项.
|
||||||
* @author LamGC
|
* @author LamGC
|
||||||
|
Loading…
Reference in New Issue
Block a user