时间轮算法

发布时间:2024年01月16日
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;
            }
        }
    }
}


文章来源:https://blog.csdn.net/qq_27735079/article/details/135628675
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。