hutool 定时任务 TimedCache - GlobalPruneTimer
今天看hutool工具中的TimedCache 时好奇他的缓存机制及定时清除原理 便简单的看了一下他的源码,总结出是
Map(缓存数据)+ScheduledExecutorService(定时清除缓存),其中的定时任务感觉比较有意思,则拷贝出来
public enum GlobalPruneTimer { /** * 单例对象 */ INSTANCE; /** * 缓存任务计数 */ private final AtomicInteger cacheTaskNumber = new AtomicInteger(1); /** * 定时器 */ private ScheduledExecutorService pruneTimer; /** * 构造 */ GlobalPruneTimer() { create(); } /** * 启动定时任务 * * @param task 任务 * @param delay 周期 * @param unit * @return {@link ScheduledFuture}对象,可手动取消此任务 */ public ScheduledFuture<?> schedule(Runnable task, int delay, TimeUnit unit) { return this.pruneTimer.scheduleAtFixedRate(task, delay, delay, unit); } /** * 创建定时器 */ public void create() { if (null != pruneTimer) { shutdownNow(); } this.pruneTimer = new ScheduledThreadPoolExecutor(1, r -> ThreadUtil.newThread(r, StrUtil.format("Pure-Timer-{}", cacheTaskNumber.getAndIncrement()))); } /** * 销毁全局定时器 */ public void shutdown() { if (null != pruneTimer) { pruneTimer.shutdown(); } } /** * 销毁全局定时器 * * @return 销毁时未被执行的任务列表 */ public List<Runnable> shutdownNow() { if (null != pruneTimer) { return pruneTimer.shutdownNow(); } return null; } }
使用例子:
/**
* DelayQueue --> Condition --> LockSupport --> Unsafe
**/
public class ScheduleTest { public static void main(String[] args) { ScheduleTest test = new ScheduleTest(); GlobalPruneTimer.INSTANCE.schedule(test::schedule,5, SECONDS);
// new ScheduledThreadPoolExecutor(1).schedule(test::schedule,5, TimeUnit.SECONDS);
} @SneakyThrows public void schedule(){ System.out.println("Start: " + DateUtil.now()); SECONDS.sleep(3); System.out.println("End : " + DateUtil.now()); } }
关键代码:通过 UNSAFE.park() 进行延迟
package java.util.concurrent.locks; import sun.misc.Unsafe; public class LockSupport { public static void parkNanos(Object blocker, long nanos) { if (nanos > 0) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, nanos); setBlocker(t, null); } } }