首页 > 编程语言 >时间轮算法及简易实现

时间轮算法及简易实现

时间:2025-01-18 20:43:18浏览次数:1  
标签:slot 实现 self interval 任务 简易 算法 时间 import

二、时间轮算法的优点

1. 高效的任务调度

  • 时间复杂度为 O(1),适合处理大量定时任务。
  • 任务的添加、删除和执行都非常高效。

2. 低内存占用

  • 时间轮通过槽和指针的方式管理任务,内存占用较低。

3. 适合高并发场景

  • 时间轮算法是无锁的,适合高并发环境。

4. 支持长时间延迟任务

  • 通过多层时间轮,可以支持长时间延迟的任务。

5. 灵活的任务管理

  • 可以方便地添加、删除和更新任务。

三、时间轮算法的实现

1. Java 实现

以下是一个单层时间轮的 Java 实现:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TimeWheel {

    private final int slotNum; // 槽数
    private final long interval; // 每个槽的时间间隔(毫秒)
    private final List<List<Runnable>> slots; // 槽中的任务列表
    private int currentSlot; // 当前指针位置
    private final ScheduledExecutorService scheduler; // 定时调度器

    public TimeWheel(int slotNum, long interval) {
        this.slotNum = slotNum;
        this.interval = interval;
        this.slots = new ArrayList<>(slotNum);
        for (int i = 0; i < slotNum; i++) {
            slots.add(new ArrayList<>());
        }
        this.currentSlot = 0;
        this.scheduler = Executors.newScheduledThreadPool(1);
        start();
    }

    // 启动时间轮
    private void start() {
        scheduler.scheduleAtFixedRate(() -> {
            // 执行当前槽的任务
            List<Runnable> tasks = slots.get(currentSlot);
            for (Runnable task : tasks) {
                task.run();
            }
            tasks.clear(); // 清空已执行的任务

            // 移动指针
            currentSlot = (currentSlot + 1) % slotNum;
        }, interval, interval, TimeUnit.MILLISECONDS);
    }

    // 添加任务
    public void addTask(Runnable task, long delay) {
        if (delay <= 0) {
            task.run();
            return;
        }
        // 计算任务所在的槽
        int targetSlot = (currentSlot + (int) (delay / interval)) % slotNum;
        slots.get(targetSlot).add(task);
    }

    // 停止时间轮
    public void stop() {
        scheduler.shutdown();
    }

    public static void main(String[] args) throws InterruptedException {
        // 创建一个时间轮,8 个槽,每个槽间隔 1 秒
        TimeWheel timeWheel = new TimeWheel(8, 1000);

        // 添加任务
        timeWheel.addTask(() -> System.out.println("Task 1 executed"), 3000); // 3 秒后执行
        timeWheel.addTask(() -> System.out.println("Task 2 executed"), 5000); // 5 秒后执行

        // 等待任务执行
        Thread.sleep(10000);

        // 停止时间轮
        timeWheel.stop();
    }
}

2. Python 实现

以下是一个单层时间轮的 Python 实现:

import threading
import time

class TimeWheel:
    def __init__(self, slot_num, interval):
        self.slot_num = slot_num
        self.interval = interval
        self.slots = [[] for _ in range(slot_num)]
        self.current_slot = 0
        self.lock = threading.Lock()
        self.running = True
        self.scheduler = threading.Thread(target=self.run)
        self.scheduler.start()

    # 启动时间轮
    def run(self):
        while self.running:
            time.sleep(self.interval / 1000)  # 转换为秒
            with self.lock:
                tasks = self.slots[self.current_slot]
                for task in tasks:
                    task()
                tasks.clear()  # 清空已执行的任务
                self.current_slot = (self.current_slot + 1) % self.slot_num

    # 添加任务
    def add_task(self, task, delay):
        if delay <= 0:
            task()
            return
        with self.lock:
            target_slot = (self.current_slot + int(delay / self.interval)) % self.slot_num
            self.slots[target_slot].append(task)

    # 停止时间轮
    def stop(self):
        self.running = False
        self.scheduler.join()

if __name__ == "__main__":
    # 创建一个时间轮,8 个槽,每个槽间隔 1 秒
    time_wheel = TimeWheel(8, 1000)

    # 添加任务
    time_wheel.add_task(lambda: print("Task 1 executed"), 3000)  # 3 秒后执行
    time_wheel.add_task(lambda: print("Task 2 executed"), 5000)  # 5 秒后执行

    # 等待任务执行
    time.sleep(10)

    # 停止时间轮
    time_wheel.stop()

四、总结与扩展

1. 总结

  • 时间轮算法是一种高效的定时任务调度算法,适合处理大量定时任务。
  • 通过槽和指针的方式,时间轮实现了 O(1) 的时间复杂度。
  • 时间轮广泛应用于网络编程、操作系统、分布式系统等场景。

2. 扩展

  • 多层时间轮
    • 对于长时间延迟的任务,可以使用多层时间轮(如秒级、分钟级、小时级)。
  • 动态扩容
    • 时间轮可以根据任务的数量动态调整槽数。
  • 分布式时间轮
    • 在分布式系统中,时间轮可以与其他算法(如一致性哈希)结合使用,实现分布式任务调度。

时间轮算法是定时任务调度领域的重要工具,掌握其原理和实现对于开发高性能系统非常有帮助。

本文由mdnice多平台发布

标签:slot,实现,self,interval,任务,简易,算法,时间,import
From: https://www.cnblogs.com/daishengli/p/18678835

相关文章

  • goIM仿微信实现小微消息沟通
    goIM仿微信实现小微消息沟通goIM小微沟通介绍开发初衷软件架构已实现功能其它试用goIM小微沟通介绍仿微信实现小型消息沟通,兼容web,微信小程序。用Go实现底层服务,uniapp实现的前端,前后端已打通。同一用户可实现多端登录,多端接收消息(如微信手机与微信PC一起开,可一......
  • K8S实现发布和回滚三种方案对比
    蓝绿部署、灰度发布、金丝雀发布和A/B测试的K8S实现方案1.蓝绿部署特点:蓝绿部署的核心思想是同时部署两个版本的应用(蓝环境和绿环境),但在某一时刻只有一个环境对外提供服务,另一环境处于待命状态,准备随时切换。缺点:一套环境空跑,资源浪费。K8S实现蓝绿发布方案:基于控制......
  • CF 265B.Roadside Trees (Simplified Edition)(Java实现)
    题目分析    松鼠的起点在第一棵树的0位置,它的行动轨迹为到达顶端,吃坚果,到另一棵树的同位置,到达顶端,吃坚果。思路分析    根据题目分析,我们需要有一个不断更新的起始位置,单次循环内的时间=到达顶端的距离+吃坚果+跳跃=顶端-起始+1+1代码        ......
  • CF 284B.Cows and Poker Game(Java实现)
    题目分析    奶牛也打扑克。一共有三种情况,简称AFI,并且只有自己为AI状态其余全部人为AF状态才可以亮手牌。思路分析    根据题目分析,针对三个不同状态分析情况:当且仅当有一个I时,唯有这个奶牛可以亮牌,如果I的个数大于1,一个也不能亮牌;当没有I时,判断A的个数,有......
  • 有一个包含开始日期和结束日期的数组,获取最小的日期和最大的日期,用java实现
    packagecom.cfb.oa.m;importjava.time.LocalDate;importjava.util.ArrayList;importjava.util.List;classDateRange{LocalDatestartDate;LocalDateendDate;publicDateRange(LocalDatestartDate,LocalDateendDate){this.startDate......
  • 基于微信小程序的大学生党务学习平台的设计与实现
    目录项目介绍系统设计系统展示核心代码项目专栏推荐为什么选择我?获取源码项目介绍如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统大学生党务学习平台信息......
  • 模态分解算法FMD-降噪-机械故障诊断
    一、模态分解算法FMD(FractionalModeDecomposition)简介基本原理FMD是一种新的信号分解方法,它能够将复杂的信号分解为一系列具有不同频率特性的模态分量。其原理是基于分数阶微积分和信号的局部特征。与传统的经验模态分解(EMD)等方法类似,它试图将信号自适应地分解成多个本......
  • 思通数科舆情监测系统:精准实现数据监测与实时预警的应用意义
    随着信息化社会的深入发展,舆情管理变得愈加复杂,尤其是在社交媒体和网络平台的广泛应用下,信息传播的速度与影响力呈现出指数级增长。如何高效监测和分析这些海量数据,成为各级政府、企业和公共机构亟待解决的问题。思通数科的舆情监测系统,凭借强大的数据监控与分析能力,能够帮助用户......
  • PowerShell 脚本调整鼠标指针的速度,虽然这不会直接影响鼠标的 DPI(硬件设置)。这个方法
    在PowerShell中,直接通过系统设置控制鼠标DPI或鼠标速度并不是一个简单的操作,因为这些设置通常依赖于硬件和驱动程序。大部分操作系统(包括Windows)本身并不提供简单的接口来直接控制DPI设置。通常,这些设置通过鼠标驱动程序或专门的鼠标软件来管理(例如:Logitech、Razer、Corsai......
  • 基于C#实现多线程启动停止暂停继续
    大家好!我是付工。大部分初学者在学习C#上位机编程时,多线程是一个很难逾越的鸿沟,不合理地使用多线程,会导致经常出现各种奇怪的问题,这也是很多初学者不敢使用多线程的原因。但是在实际开发中,多线程是一个不可避免的技术栈,基本上每个项目都会使用到,因此学好多线程技术,很重要。一、......