153 lines
2.7 KiB
Go
153 lines
2.7 KiB
Go
package queue
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
)
|
||
|
||
// 延迟消息
|
||
type DelayMessage struct {
|
||
//当前下标
|
||
curIndex int
|
||
//环形槽
|
||
slots [3600]map[string]*Task
|
||
//关闭
|
||
closed chan bool
|
||
//任务关闭
|
||
taskClose chan bool
|
||
//时间关闭
|
||
timeClose chan bool
|
||
//启动时间
|
||
startTime time.Time
|
||
}
|
||
|
||
// 执行的任务函数
|
||
type TaskFunc func(args ...interface{})
|
||
|
||
// 任务
|
||
type Task struct {
|
||
//循环次数
|
||
cycleNum int
|
||
//执行的函数
|
||
exec TaskFunc
|
||
params []interface{}
|
||
}
|
||
|
||
// 创建一个延迟消息
|
||
func NewDelayMessage() *DelayMessage {
|
||
dm := &DelayMessage{
|
||
curIndex: 0,
|
||
closed: make(chan bool),
|
||
taskClose: make(chan bool),
|
||
timeClose: make(chan bool),
|
||
startTime: time.Now(),
|
||
}
|
||
for i := 0; i < 3600; i++ {
|
||
dm.slots[i] = make(map[string]*Task)
|
||
}
|
||
return dm
|
||
}
|
||
|
||
// 启动延迟消息
|
||
func (dm *DelayMessage) Start() {
|
||
go dm.taskLoop()
|
||
go dm.timeLoop()
|
||
select {
|
||
case <-dm.closed:
|
||
{
|
||
dm.taskClose <- true
|
||
dm.timeClose <- true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// 关闭延迟消息
|
||
func (dm *DelayMessage) Close() {
|
||
dm.closed <- true
|
||
}
|
||
|
||
// 处理每1秒的任务
|
||
func (dm *DelayMessage) taskLoop() {
|
||
defer func() {
|
||
fmt.Println("taskLoop exit")
|
||
}()
|
||
for {
|
||
select {
|
||
case <-dm.taskClose:
|
||
{
|
||
return
|
||
}
|
||
default:
|
||
{
|
||
//取出当前的槽的任务
|
||
tasks := dm.slots[dm.curIndex]
|
||
if len(tasks) > 0 {
|
||
//遍历任务,判断任务循环次数等于0,则运行任务
|
||
//否则任务循环次数减1
|
||
for k, v := range tasks {
|
||
if v.cycleNum == 0 {
|
||
go v.exec(v.params...)
|
||
//删除运行过的任务
|
||
delete(tasks, k)
|
||
} else {
|
||
v.cycleNum--
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理每1秒移动下标
|
||
func (dm *DelayMessage) timeLoop() {
|
||
defer func() {
|
||
fmt.Println("timeLoop exit")
|
||
}()
|
||
tick := time.NewTicker(time.Second)
|
||
for {
|
||
select {
|
||
case <-dm.timeClose:
|
||
{
|
||
return
|
||
}
|
||
case <-tick.C:
|
||
{
|
||
//fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
|
||
//判断当前下标,如果等于3599则重置为0,否则加1
|
||
if dm.curIndex == 3599 {
|
||
dm.curIndex = 0
|
||
} else {
|
||
dm.curIndex++
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 添加任务
|
||
func (dm *DelayMessage) AddTask(t time.Time, key string, exec TaskFunc, params []interface{}) error {
|
||
if dm.startTime.After(t) {
|
||
return errors.New("时间错误")
|
||
}
|
||
//当前时间与指定时间相差秒数
|
||
subSecond := t.Unix() - dm.startTime.Unix()
|
||
//计算循环次数
|
||
cycleNum := int(subSecond / 3600)
|
||
//计算任务所在的slots的下标
|
||
ix := subSecond % 3600
|
||
//把任务加入tasks中
|
||
tasks := dm.slots[ix]
|
||
if _, ok := tasks[key]; ok {
|
||
return errors.New("该slots中已存在key为" + key + "的任务")
|
||
}
|
||
tasks[key] = &Task{
|
||
cycleNum: cycleNum,
|
||
exec: exec,
|
||
params: params,
|
||
}
|
||
return nil
|
||
}
|