[Change] CacheStore-Local 调整 AutoCleanTimer 初始化细节, 将 AutoCleanTimer 对 Cleanable 的强引用改为弱引用;

[Change] AutoCleanTimer 简化 static 代码块内容, 移除 debug 相关代码(目前用不上);
[Change] AutoCleanTimer 对 Cleanable 的强引用改为弱引用, 以防止 CacheStore 无法被回收导致内存泄漏;
This commit is contained in:
LamGC 2020-10-18 14:34:01 +08:00
parent 11327a368f
commit e2c6aca34c
Signed by: LamGC
GPG Key ID: 6C5AE2A913941E1D

View File

@ -5,12 +5,14 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* 定时清理机制. * 定时清理机制.
@ -20,7 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/ */
public class AutoCleanTimer implements Runnable { public class AutoCleanTimer implements Runnable {
private final static Set<Cleanable> CLEANABLE_STORE_SET = new CopyOnWriteArraySet<>(); private final static Set<WeakReference<Cleanable>> CLEANABLE_STORE_SET = new CopyOnWriteArraySet<>();
private final static ScheduledExecutorService SCHEDULED_EXECUTOR = private final static ScheduledExecutorService SCHEDULED_EXECUTOR =
new ScheduledThreadPoolExecutor(1, new ScheduledThreadPoolExecutor(1,
@ -32,22 +34,9 @@ public class AutoCleanTimer implements Runnable {
private final static Logger log = LoggerFactory.getLogger(AutoCleanTimer.class); private final static Logger log = LoggerFactory.getLogger(AutoCleanTimer.class);
private final static AtomicBoolean DEBUG_ENABLE = new AtomicBoolean(false);
static { static {
SCHEDULED_EXECUTOR.scheduleAtFixedRate(new AutoCleanTimer(), 100L, 100L, TimeUnit.MILLISECONDS); SCHEDULED_EXECUTOR.scheduleAtFixedRate(new AutoCleanTimer(), 100L, 100L, TimeUnit.MILLISECONDS);
Thread shutdownHook = new Thread(SCHEDULED_EXECUTOR::shutdown); Runtime.getRuntime().addShutdownHook(new Thread(SCHEDULED_EXECUTOR::shutdownNow, "ShutdownThread-AutoClean"));
shutdownHook.setName("ShutdownThread-AutoClean");
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
/**
* 是否启用调试模式.
* <p>启用后将会打印相关日志.
* @param enable 是否启用调试模式.
*/
public static void setDebugEnable(boolean enable) {
DEBUG_ENABLE.set(enable);
} }
/** /**
@ -55,15 +44,7 @@ public class AutoCleanTimer implements Runnable {
* @param store 已实现Cleanable的对象 * @param store 已实现Cleanable的对象
*/ */
public static void add(Cleanable store) { public static void add(Cleanable store) {
CLEANABLE_STORE_SET.add(store); CLEANABLE_STORE_SET.add(new WeakReference<>(store));
}
/**
* 移除已添加的缓存库
* @param store 需要从AutoCleanTimer移除的对象
*/
public static void remove(Cleanable store) {
CLEANABLE_STORE_SET.remove(store);
} }
private AutoCleanTimer() {} private AutoCleanTimer() {}
@ -74,12 +55,23 @@ public class AutoCleanTimer implements Runnable {
return; return;
} }
CLEANABLE_STORE_SET.forEach(cleanable -> { Iterator<WeakReference<Cleanable>> iterator = CLEANABLE_STORE_SET.iterator();
try { Set<WeakReference<Cleanable>> toBeCleanReference = new HashSet<>();
cleanable.clean(); while(iterator.hasNext()) {
} catch (Exception e) { WeakReference<Cleanable> reference = iterator.next();
log.error("{} 执行清理动作时发生异常:\n{}", cleanable.toString(), Throwables.getStackTraceAsString(e)); Cleanable store = reference.get();
if (store == null) {
// 由于 COW ArraySet Iterator 不支持 remove 操作,
// 所以先收集起来, 等完成所有清理工作后统一删除引用.
toBeCleanReference.add(reference);
return;
} }
}); try {
store.clean();
} catch (Exception e) {
log.error("{} 执行清理动作时发生异常:\n{}", store.toString(), Throwables.getStackTraceAsString(e));
}
}
CLEANABLE_STORE_SET.removeAll(toBeCleanReference);
} }
} }