package com.rural_vibration.common.utils;
import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class TimeWheelTest {
// 时间轮大小,每一格代表1秒
private final int WHEEL_SIZE = 60;
// 时间轮的每一格,用来存储定时任务
private TimeSlot[] timeSlots;
// 当前指针指向的时间槽
private int currentSlotIndex = 0;
// 下一级时间轮
private TimeWheelTest nextLevelWheel;
// 延迟队列,用来存储需要延迟执行的任务
private DelayQueue<Task> delayQueue = new DelayQueue<>();
public TimeWheelTest() {
this.timeSlots = new TimeSlot[WHEEL_SIZE];
for (int i = 0; i < WHEEL_SIZE; i++) {
this.timeSlots[i] = new TimeSlot();
}
}
// 添加任务
public void addTask(Task task) {
long delay = task.getDelay(TimeUnit.SECONDS);
if (delay < WHEEL_SIZE) {
// 在当前时间轮的对应时间槽中添加任务
int index = (currentSlotIndex + (int) delay) % WHEEL_SIZE;
timeSlots[index].addTask(task);
} else {
// 在下一级时间轮中添加任务
if (nextLevelWheel == null) {
synchronized (this) {
if (nextLevelWheel == null) {
nextLevelWheel = new TimeWheelTest();
}
}
}
nextLevelWheel.addTask(task);
}
}
// 执行任务
public void run() {
// 获取延迟队列中已经到期的任务
Task task = delayQueue.poll();
while (task != null) {
addTask(task);
task = delayQueue.poll();
}
// 执行当前时间槽中的任务
timeSlots[currentSlotIndex].run();
// 指针向前移动一格
currentSlotIndex = (currentSlotIndex + 1) % WHEEL_SIZE;
// 如果有下一级时间轮,则执行下一级时间轮的任务
if (nextLevelWheel != null) {
nextLevelWheel.run();
}
}
// 时间轮中的时间槽,用来存储任务
private class TimeSlot {
private TaskList taskList = new TaskList();
public void addTask(Task task) {
taskList.addTask(task);
}
public void run() {
taskList.run();
}
}
// 任务链表
private class TaskList {
private TaskNode head;
private TaskNode tail;
public void addTask(Task task) {
TaskNode node = new TaskNode(task);
if (head == null) {
head = tail = node;
} else {
tail.next = node;
tail = node;
}
}
public void run() {
TaskNode node = head;
while (node != null) {
node.task.run();
node = node.next;
}
}
}
// 任务节点
private static class TaskNode {
private Task task;
private TaskNode next;
public TaskNode(Task task) {
this.task = task;
}
}
// 任务类,实现Delayed接口
private static class Task implements Delayed {
private long startTime; // 任务开始时间
private Runnable runnable; // 任务执行的内容
public Task(long delay, Runnable runnable) {
this.startTime = System.currentTimeMillis() + delay * 1000;
this.runnable = runnable;
}
@Override
public long getDelay(TimeUnit unit) {
long delay = startTime - System.currentTimeMillis();
return unit.convert(delay, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
long delay = getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
if (delay < 0) {
return -1;
} else if (delay > 0) {
return 1;
} else {
return 0;
}
}
public void run() {
runnable.run();
}
}
public static void main(String[] args) throws InterruptedException {
TimeWheelTest timeWheel = new TimeWheelTest();
int time = 0;
// 添加10个任务,分别延迟1秒、2秒、3秒、4秒、5秒、6秒、7秒、8秒、9秒和10秒执行
for (int i = 1; i <= 10; i++) {
final int delay = i;
timeWheel.addTask(new Task(delay, () -> System.out.println("Task " + delay + " is executed. now: " + new Date().getTime())));
System.out.println("正在添加任务"+ i);
}
// 每秒钟执行一次时间轮
while (true) {
timeWheel.run();
Thread.sleep(1000);
System.out.println("\r\n" + "\t" + "========================================================="+ ++time);
if (time >= 60){
time=1;
}
}
}
}