我们定义了TimeWheel和slot两个结构体。其中,TimeWheel代表整个时间轮,包括多个时间轮槽;slot代表一个时间轮槽,用于存储当前槽位上的所有任务。
在NewTimeWheel函数中,我们初始化了一个TimeWheel结构体,并创建了指定数量的时间轮槽。在每个槽中,我们创建了一个taskList字段,用于存储当前槽位上的所有任务。在AddTask函数中,我们首先计算出任务应该被添加到哪个槽位,然后将任务添加到该槽位对应的taskList中。在tick函数中,我们首先将时间轮指针指向下一个槽位,然后执行该槽位上的所有任务。执行完毕后,我们需要将当前槽位的taskList清空,以便下一次任务添加。
在main函数中,我们创建了一个新的时间轮,然后添加了三个任务,分别延迟10秒、20秒和30秒执行。我们等待35秒钟,让任务得以全部执行完毕,然后关闭时间轮。
需要注意的是,上述实现中的时间轮是基于Go语言的定时器实现的。定时器是一种高效的时间管理机制,它可以在一定程度上保证任务的及时执行。但是,它也有一些局限性,比如无法处理任务执行时间超过定时器时间间隔的情况。如果需要更加精确的任务调度,可以考虑使用其他更加复杂的机制,比如堆或优先队列等。
package main
import (
"container/list"
"fmt"
"time"
)
const (
// 时间轮槽数量
wheelSize = 60
// 时间轮每个槽位的时间间隔,单位为秒
tickInterval = 1
)
// 时间轮槽结构体,用于存储当前槽位上的所有任务
type slot struct {
taskList *list.List
}
// 时间轮结构体
type TimeWheel struct {
// 当前时间轮指针指向的槽位
currentIndex int
// 时间轮槽数组
slots []*slot
// 槽数量
wheelSize int
// 每个槽位的时间间隔
tickInterval time.Duration
// 定时器
ticker *time.Ticker
}
// 新建一个时间轮
func NewTimeWheel(wheelSize int, tickInterval time.Duration) *TimeWheel {
tw := &TimeWheel{
slots: make([]*slot, wheelSize),
wheelSize: wheelSize,
tickInterval: tickInterval,
ticker: time.NewTicker(tickInterval * time.Second),
}
for i := 0; i < wheelSize; i++ {
tw.slots[i] = &slot{
taskList: list.New(),
}
}
return tw
}
// 启动时间轮
func (tw *TimeWheel) Start() {
go func() {
for range tw.ticker.C {
tw.tick()
}
}()
}
// 关闭时间轮
func (tw *TimeWheel) Stop() {
tw.ticker.Stop()
}
// 添加任务到时间轮
func (tw *TimeWheel) AddTask(delay time.Duration, task func()) {
ticks := int(delay.Seconds() / tw.tickInterval.Seconds())
index := (tw.currentIndex + ticks) % tw.wheelSize
tw.slots[index].taskList.PushBack(task)
}
// 时间轮指针指向下一个槽位,并执行该槽位上的所有任务
func (tw *TimeWheel) tick() {
tw.currentIndex = (tw.currentIndex + 1) % tw.wheelSize
slot := tw.slots[tw.currentIndex]
for e := slot.taskList.Front(); e != nil; e = e.Next() {
task := e.Value.(func())
task()
}
slot.taskList = list.New()
}
func main() {
tw := NewTimeWheel(wheelSize, tickInterval)
tw.Start()
// 添加一个任务,延迟10秒执行
tw.AddTask(10*time.Second, func() {
fmt.Println("task 1 executed")
})
// 添加一个任务,延迟20秒执行
tw.AddTask(20*time.Second, func() {
fmt.Println("task 2 executed")
})
// 添加一个任务,延迟30秒执行
tw.AddTask(30*time.Second, func() {
fmt.Println("task 3 executed")
})
// 等待任务执行完成
time.Sleep(35 * time.Second)
// 关闭时间轮
tw.Stop()
}