作者:微信小助手
发布时间:2020-02-12T16:24:28
点击▲关注 “爪哇笔记” 给公众号标星置顶
更多精彩 第一时间直达
时间轮是一种高效、低延迟的调度数据结构。其在Linux内核中广泛使用,是Linux内核定时器的实现方法和基础之一。按使用场景,大致可以分为两种时间轮:原始时间轮和分层时间轮。分层时间轮是原始时间轮的升级版本,来应对时间“槽”数量比较大的情况,对内存和精度都有很高要求的情况。延迟任务的场景一般只需要用到原始时间轮就可以了。
推荐使用Netty
提供的HashedWheelTimer
工具类来实现延迟任务。
引入依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
<version>4.1.23.Final</version>
</dependency>
红包过期队列信息:
/**
* 红包过期队列信息
*/
public class RedPacketTimerTask implements TimerTask {
private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
/**
* 红包 ID
*/
private final long redPacketId;
/**
* 创建时间戳
*/
private final long timestamp;
public RedPacketTimerTask(long redPacketId) {
this.redPacketId = redPacketId;
this.timestamp = System.currentTimeMillis();
}
@Override
public void run(Timeout timeout) {
//异步处理任务
System.out.println(String.format("任务执行时间:%s,红包创建时间:%s,红包ID:%s",
LocalDateTime.now().format(F), LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).format(F), redPacketId));
}
}
测试用例:
/**
* 基于 netty 的时间轮算法 HashedWheelTimer 实现的延迟任务
*/
public class RedPacketHashedWheelTimer {
private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
public static void main(String[] args) throws Exception {
ThreadFactory factory = r -> {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("RedPacketHashedWheelTimerWorker");
return thread;
};
/**
* @param tickDuration - 每tick一次的时间间隔
* @param unit - tickDuration 的时间单位
* @param ticksPerWheel - 时间轮中的槽数
* @param leakDetection - 检查内存溢出
*/
Timer timer = new HashedWheelTimer(factory, 1,
TimeUnit.SECONDS, 100,true);
System.out.println(String.format("开始任务时间:%s",LocalDateTime.now().format(F)));
for(int i=1;i<10;i++){
TimerTask timerTask = new RedPacketTimerTask(i);
timer.newTimeout(timerTask, i, TimeUnit.SECONDS);
}
Thread.sleep(Integer.MAX_VALUE);
}
}
打印任务执行日志:
开始任务时间:2020-02-12 15:22:23.404
任务执行时间:2020-02-12 15:22:25.410,红包创建时间:2020-02-12