golang延时_golang 实现延迟消息原理与方法

实现延迟消息具体思路我是看的下面这篇文章

https://mp.weixin.qq.com/s/eDMV25YqCPYjxQG-dvqSqQ

实现延迟消息最主要的两个结构:

环形队列:通过golang中的数组实现,分成3600个slot。

任务集合:通过map[key]*Task,每个slot一个map,map的值就是我们要执行的任务。

原理图如下:

0dedc46bd39c5e4ca5db4fe178b54aaa.png

实现代码如下:

package main;

import (

"time"

"errors"

"fmt"

)

//延迟消息

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.taskClose

dm.timeClose

break;

}

};

}

//关闭延迟消息

func (dm *DelayMessage) Close() {

dm.closed

}

//处理每1秒的任务

func (dm *DelayMessage) taskLoop() {

defer func() {

fmt.Println("taskLoop exit");

}();

for {

select {

case

{

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

{

return;

}

case

{

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;

}

func main() {

//创建延迟消息

dm := NewDelayMessage();

//添加任务

dm.AddTask(time.Now().Add(time.Second*10), "test1", func(args ...interface{}) {

fmt.Println(args...);

}, []interface{}{1, 2, 3});

dm.AddTask(time.Now().Add(time.Second*10), "test2", func(args ...interface{}) {

fmt.Println(args...);

}, []interface{}{4, 5, 6});

dm.AddTask(time.Now().Add(time.Second*20), "test3", func(args ...interface{}) {

fmt.Println(args...);

}, []interface{}{"hello", "world", "test"});

dm.AddTask(time.Now().Add(time.Second*30), "test4", func(args ...interface{}) {

sum := 0;

for arg := range args {

sum += arg;

}

fmt.Println("sum : ", sum);

}, []interface{}{1, 2, 3});

//40秒后关闭

time.AfterFunc(time.Second*40, func() {

dm.Close();

});

dm.Start();

}

测试结果如下:

571503bf69ad6d809fd114fbdd2b7d5d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python特征工程插件_手把手教你用Python实现自动特征工程

任何参与过机器学习比赛的人&#xff0c;都能深深体会特征工程在构建机器学习模型中的重要性&#xff0c;它决定了你在比赛排行榜中的位置。 特征工程具有强大的潜力&#xff0c;但是手动操作是个缓慢且艰巨的过程。Prateek Joshi&#xff0c;是一名数据科学家&#xff0c;花了…

2020笔记本性价比之王_笔记本电脑性价比排行2020前十名?

展开全部1、 联想(Lenovo)拯救者R7000产品材质&#xff1a;32313133353236313431303231363533e58685e5aeb931333433656631ABCD面塑料产品尺寸&#xff1a;15.6寸CPU型号&#xff1a; AMD Ryzen5 4600H显卡型号&#xff1a;NVIDIA GeForce GTX 1650屏幕参数&#xff1a; 1080P I…

ios不行安卓可以 微信签名_王者荣耀安卓、iOS互通来了!现在可以互看好友资料...

3月10日消息&#xff0c;王者荣耀在更新正式服后&#xff0c;安卓版和iOS版开通了资料互看。此前安卓和iOS上的游戏一直因为使用的服务器不同&#xff0c;不能实现两个平台的游戏互动&#xff0c;当然也不能实现同账号的资料同步。这对很多玩家来说造成一定的困扰&#xff0c;如…

存储型xss漏洞怎么解决_FinDOMXSS:一款针对DOM型XSS漏洞的快速扫描工具

FinDOM-XSSFinDOM-XSS是一款针对DOM型XSS漏洞的快速扫描工具&#xff0c;广大安全研究人员可以利用FinDOM-XSS快速地发现/扫描出目标应用中潜在的DOM型XSS漏洞。工具安装广大研究人员可以使用下列命令将该项目源码克隆至本地&#xff1a;$ git clone https://github.com/dwisis…

c语言如何判断数据是否符合正态分布_统计学里的数据正态性检验

在前面的文章中讲过&#xff0c;很多模型的假设条件都是数据是服从正态分布的。这篇文章主要讲讲如何判断数据是否符合正态分布。主要分为两种方法&#xff1a;描述统计方法和统计检验方法。01.描述统计方法描述统计就是用描述的数字或图表来判断数据是否符合正态分布。常用的方…

python matplotlib_Python の Matplotlib

matplotlib是python优秀的数据可视化第三方库。matplotlib.pyplot子库可以调用全部功能&#xff0c;便于用户使用。绘图-plt.plot(x,y,format,**kwargs)x&#xff1a;x轴数据y&#xff1a;y轴数据format_string&#xff1a;控制曲线的格式字符串&#xff0c;颜色线条点**kwargs…

mysql 数据库还原 不齐_请教mysql数据库还原问题。

你的位置:问答吧-> 数据库-> 问题详情请教mysql数据库还原问题。50多m&#xff0c;能不能拆分&#xff1f;上传到服务器上总是超时。怎么办&#xff1f;[ 本帖最后由 geniux 于 2007-9-24 15:23 编辑 ]作者: geniux发布时间: 2007-09-20继续请教&#xff0c;现在数据库传…

python self理解_Python面向对象总结,让你快速掌握面向对象常用的用法

python等面向对象的提出是为了更好的处理和管理同属一个类别的事情&#xff0c;这样就可以省去多余重复的基础代码&#xff0c;让程序变得更加简洁和强大。对于学习编程的朋友来说&#xff0c;熟悉掌握面向对象是非常重要的。下面开始讲讲关于python面向对象的知识&#xff0c;…

mysql 查询 汇总_Mysql-Sql查询汇总

软件测试Mysql-Sql查询汇总简单查询创建students表create table students(id int not null unique primary key auto_increment,name varchar(10) not null,class varchar(10) not null,grade int)添加数据insert into students values(0,老1,1班,80);insert into students val…

pat和ccf哪个含金量高_函授和网络教育哪个好 哪个含金量高

函授和网络教育都是成人教育学习的方式&#xff0c;但是考生报考的时候选择哪个比较好&#xff0c;下面小编整理了相关信息&#xff0c;以供参考。一、函授好还是网络教育好其实这两种教育方式都各有各的优点&#xff0c;两者都是不可替代的&#xff0c;这两种方式对于不同阶段…

mysql各种联结的区别_mysql几种连接方式区别

mysql的几种join2017年03月19日 14:49:07 carl-zhao 阅读数&#xff1a;7845 标签&#xff1a; mysqlsqljoin 更多个人分类&#xff1a; MySQL版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/u012410733/article/details/63…

python和office_Python在office开发中的应用

Python with Excel 有几个很好的Python模块能够方便地操作Excel的数据&#xff0c;包括读与写&#xff0c;不要求本地安装Excel。例如pandas, openpyxl, xlrd, xlutils 和 pyexcel. 详情可以参考下面的介绍&#xff1a; https://www.datacamp.com/community/tutorials/python-e…

android通过用户名密码访问服务器获取信息_MySQL ------ 管理用户对数据库的访问控制(GRANT 与 REVOKE)(二十九)...

数据库服务器通常包含着关键的数据&#xff0c;所以为了确保这些数据的安全和完整需要要利用访问控制。MySQL服务器的安全基础是&#xff1a;用户应该对他们需要的数据具有适当的访问权&#xff0c;既不能多也不能少&#xff08;即用户不能对过多的数据具有访问权&#xff09;访…

mysql安全补丁如何处理_3分钟学会mysql数据库的逻辑架构原理

这篇文章主要是从mysql数据库的逻辑架构来认识掌握mysql的原理。只要是稍微有一点计算机的相关知识相信都能看明白。一、笼统的逻辑架构先给出一张逻辑架构图&#xff0c;这张图是让你从宏观的角度来分析认识一下。从这张图你可以获取到如下的信息&#xff1a;&#xff08;1&am…

onclick 源码_仿照React源码流程打造90行代码的Hooks

作者&#xff1a;苏畅转发链接&#xff1a;https://mp.weixin.qq.com/s/YLSD4IojDWTPlov_RQtVAA前言你可能已经看过其它简易的Hooks实现。那么本文和其它实现有什么区别呢&#xff1f;本文的实现完全参照React源码的运行流程。学懂本文&#xff0c;去看React源码&#xff0c;你…

java写一个窗体并连接MySQL_大神帮忙写一个简单地java页面,连接MySQL数据库之后能够显示数据库上的数据...

展开全部用jdbc 连接mysql数据库就行了&#xff0c;网上搜下一大把。--记得在classpath下加入mysql 的jdbc驱动包。/*** author &#xff1a;来e68a84e8a2ad3231313335323631343130323136353331333337386636自互联网*/import java.sql.DriverManager;import java.sql.ResultSet…

java break 在if 中使用_java中使用国密SM4算法详解

前言上次总结了一下加密算法的分类&#xff08;加密算法有集中形式&#xff0c;各有什么不同&#xff1f;&#xff09;&#xff0c;现在我们用java语言实现一下SM4:无线局域网标准的分组数据算法。对称加密&#xff0c;密钥长度和分组长度均为128位。ps&#xff1a;我们既可以基…

移动web前端开发框架_移动前端开发是Web前端开发吗?

移动端开发并不是Web前端开发&#xff0c;但移动前端开发和web前端开发其实都属于前端开发的范围&#xff0c;目前前端发展的趋势就是大前端&#xff0c;可以说是包罗万象。但不论趋势如何发展&#xff0c;目前来看HTML、CSS和JavaScript依然是整个前端开发的三大基石。所以不论…

mtk一键usb驱动_三菱MRJEB驱动器报错,导致报错原因37.1参数设置范围异常?

三菱MR-JE-B驱动器报错&#xff0c;导致报错原因37.1参数设置范围异常&#xff1f;最近海蓝机电工程师们在做一个项目&#xff0c;做的是三菱MR-JE-B驱动器。工程师们在实操这个项目过程中遇到各种问题&#xff0c;其中就像驱动器报错的问题&#xff0c;导致报错的原因显示37,1…

将虚拟主机加入到netskills.net域环境_网站建设阿里云虚拟主机、ECS服务器、企业邮箱选择购买指南...

对于刚接触阿里云的人来说可能看到阿里云的产品介绍页面会比较头晕&#xff0c;各种产品分类&#xff0c;而且同一个产品在不同的分类目录下都能看到&#xff0c;下面简单介绍一下制作网站过程中常用的阿里云的产品。阿里云在网站建设方面常用的服务主要有云虚拟主机、ECS云服务…