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);
         }
     }
}

 

posted @ 2021-07-29 14:37  真某人  阅读(1100)  评论(0编辑  收藏  举报