基于简单时间轮的定时任务功能

定时任务

定时任务底层涉及到的数据结构与算法有很多种,如
nginx:红黑树,Go:小顶堆,Linux内核:时间轮

时间轮可以分为简单时间轮和层级时间轮,如下粗糙的实现了基于简单时间轮的定时任务功能。

package main

import (
	"fmt"
	"sync/atomic"
	"time"
)

const SECONDS = 60

type task []struct {
	stop   bool
	doTime uint32
	do     func()
}

type Timer struct {
	seconds     [SECONDS]task
	currentTime uint32
}

func NewTimer() *Timer {

	t := &Timer{
		seconds:     [60]task{},
		currentTime: 0,
	}
	go func() {
		for {
			for i := 0; i < 5; i++ {
				time.Sleep(time.Millisecond * 200)
			}
			atomic.StoreUint32(&t.currentTime, atomic.AddUint32(&t.currentTime, +1))
		}
	}()

	go func() {
		for {
			index := atomic.LoadUint32(&t.currentTime) % SECONDS
			tasks := t.seconds[index]
			for idx := range tasks {
				if tasks[idx].stop == false && tasks[idx].doTime <= atomic.LoadUint32(&t.currentTime) {
					tasks[idx].stop = true
					go tasks[idx].do()
				}
			}
			
			for i := 0; i < 3; i++ {
				time.Sleep(time.Millisecond * 200)
			}
		}
	}()
	return t
}

func (t *Timer) AfterFunc(second uint32, fn func()) {
	index := atomic.LoadUint32(&t.currentTime) + second
	t.seconds[index%SECONDS] = append(t.seconds[index%SECONDS], struct {
		stop   bool
		doTime uint32
		do     func()
	}{stop: false, doTime: index, do: fn})
}

func main() {
	t := NewTimer()

	t.AfterFunc(5, func() {
		fmt.Println("hello world")
	})

	t.AfterFunc(60, func() {
		fmt.Println("hello world1")
	})

	t.AfterFunc(10, func() {
		fmt.Println("hello 10s")
	})

	time.Sleep(time.Second * 100)
}

你可能感兴趣的:(数据结构与算法,时间轮)