java时间轮定时器_基于时间轮的定时器
基于时间轮的定时器
原理
图片是一个单层时间轮,当指针走到某一格上,就获取那一格上挂的任务将其执行。
当时如果时间跨度大的时候,格子数明显不够,那么就可以做成多级时间轮。
其实就是当低层的时间轮走了一圈,将它高一层的时间轮走一格,并且将挂在高层时间轮上的任务分配下来。
实现
文件#include"TimeWheel.h"
#include
#include
#include
#include
struct TimeStamp //时间戳
{
int ms;
int s;
int min;
bool operator==(TimeStamp timeStamp)
{
return timeStamp.ms==ms&&timeStamp.s==s&&timeStamp.min==min;
}
};
struct Event //挂在时间槽上的事件
{
std::function call_back;
TimeStamp tri_time; //事件触发的时间
int dur; //多久触发
};
class TimeWheel //时间轮
{
public:
TimeWheel();
~TimeWheel();
void Start(); //启动
int AddTimer(int space,std::function& call_back); //添加定期器
private:
void DoLoop();//主循环
void InsertTimer(Event &event); //插入事件到时间槽
int getMS(const TimeStamp &timeStamp);
void solvingEvents(std::listl); //解决时间槽上的事件
void getNextTime(TimeStamp &nowTimeStamp,int dur); //得到下个时间
private:
std::list *callBackList = nullptr; //当做时间槽上,每一个槽都是一个链表
std::mutex _mutex; //互斥量
TimeStamp timeStamp; //事件轮的时间
int slot_ms; //毫秒的时间槽数量
int slot_s; //秒的时间槽数量
int slot_min; //分的时间槽数量
int step; //最小的间隔时间
};
文件#include"TimeWheel.cpp"
#include"TimeWheel.h"
#include
using namespace std;
TimeWheel::TimeWheel()
{
cout<
timeStamp.ms = timeStamp.s = timeStamp.min = 0;
slot_ms=10;
slot_s=60;
slot_min=60;
step = 100;
callBackList = new list[slot_ms+slot_s+slot_min];
}
TimeWheel::~TimeWheel()
{
delete[] callBackList;
}
void TimeWheel::Start() //开启一个线程
{
cout<
std::thread myThread([&]{
this->DoLoop();
});
myThread.detach();
}
void TimeWheel::DoLoop() //主循环
{
cout<
while(true)
{
this_thread::sleep_for(chrono::milliseconds(step)); //让线程休息step毫秒的时间
unique_lock<:mutex> lock(_mutex);
cout<
TimeStamp per = timeStamp; //per是原来的时间
getNextTime(timeStamp,step); //timeStamp向后走一步
if(per.min!=timeStamp.min) //分针有进位
{
//cout<
list& l = callBackList[slot_ms+slot_s+timeStamp.min];
solvingEvents(l);
l.clear();
}
else if(per.s!=timeStamp.s) //秒针有进位
{
//cout<
list& l = callBackList[slot_ms+timeStamp.s];
solvingEvents(l);
l.clear();
}
else if(per.ms!=timeStamp.ms) //毫秒有进位
{
//cout<
list& l = callBackList[timeStamp.ms];
solvingEvents(l);
l.clear();
}
lock.unlock();
}
}
int TimeWheel::getMS(const TimeStamp &timeStamp) //得到时间戳timeStamp一共多少ms
{
return step * timeStamp.ms + timeStamp.s * 1000 + timeStamp.min * 60 * 1000;
}
void TimeWheel::solvingEvents(listl)
{
for (auto item = l.begin(); item != l.end(); item++)
{
if(timeStamp == item->tri_time) //触发时间到了
{
item->call_back(); //执行函数
//如果需要发生多次加入下面两行
getNextTime(item->tri_time,item->dur);
InsertTimer(*item);
}
else
{
InsertTimer(*item);
}
}
}
void TimeWheel::getNextTime(TimeStamp &nowTimeStamp,int dur)//获得下一个时间
{
int next_ms = getMS(nowTimeStamp)+dur;
nowTimeStamp.min = next_ms/1000/60%slot_min;
nowTimeStamp.s = (next_ms%(1000*60))/1000;
nowTimeStamp.ms = (next_ms%1000)/step;
}
//添加定时器
int TimeWheel::AddTimer(int space,function& call_back)
{
if(space
if(space%step!=0)return -1;
unique_lock<:mutex> lock(_mutex);
Event event;
event.call_back = call_back;
event.tri_time.ms = timeStamp.ms;
event.tri_time.s = timeStamp.s;
event.tri_time.min = timeStamp.min;
event.dur = space;
getNextTime(event.tri_time,event.dur);
//cout<
cout<
InsertTimer(event);
lock.unlock();
return 0;
}
//先时间轮内插入事件
void TimeWheel::InsertTimer(Event &event)
{
if(event.tri_time.min != timeStamp.min) //分钟与现在不同的分钟就插入分的槽
callBackList[slot_ms + slot_s + event.tri_time.min].push_back(event);
else if(event.tri_time.s != timeStamp.s)
callBackList[slot_ms + event.tri_time.s].push_back(event);
else if(event.tri_time.ms != timeStamp.ms)
callBackList[event.tri_time.ms].push_back(event);
}
测试文件Main.cpp
#include
#include
#include"TimeWheel.h"
#include
using namespace std;
void fun100()
{
cout << "------------fun 100--------------" << endl;
}
void fun200()
{
cout << "------------fun 200--------------" << endl;
}
void fun500()
{
cout << "------------fun 500--------------" << endl;
}
void fun1500()
{
cout << "------------fun 1500-------------" << endl;
}
int main()
{
function f100 = std::bind(&fun100);
function f200 = std::bind(&fun200);
function f500 = std::bind(&fun500);
function f1500 = std::bind(&fun1500);
TimeWheel timeWheel;
timeWheel.Start();
//加入定时器
timeWheel.AddTimer(100,f100);
timeWheel.AddTimer(200,f200);
timeWheel.AddTimer(500,f500);
timeWheel.AddTimer(1500,f1500);
while(true){}
return 0;
}
实现效果
java时间轮定时器_基于时间轮的定时器相关推荐
- uuid表示时间的部分_基于时间UUID的妙用
1.jar包获取 https://github.com/cowtowncoder/java-uuid-generator/ com.fasterxml.uuid java-uuid-generator ...
- java项目----教务管理系统_基于Java的教务管理系统
java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...
- java线程轮询_基于springboot实现轮询线程自动执行任务
本文使用: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行, 但不能在指定 ...
- java 长轮询_基于springboot 长轮询的实现操作
springboot 长轮询实现 基于 @EnableAsync , @Sync @SpringBootApplication @EnableAsync public class DemoApplic ...
- java 解析日期格式_日期/时间格式/解析,Java 8样式
java 解析日期格式 自Java 几乎 开始以来,Java开发人员就通过java.util.Date类(自JDK 1.0起)和java.util.Calendar类(自JDK 1.1起 )来处理日期 ...
- monkey 运行时间怎么计算_基于STM32F103C8T6工控板利用定时器计算某段代码的运行时间...
本人参考了热心网友分享的一些案例,并增加了一些个人认为比较好的想法,重新整合了一下代码. 硬件:某宝网上购买的STM32F103C8T6工控板,价格50¥左右: 思路: 1)利用通用定时器(选择定时器 ...
- java网上书店系统_基于JAVA/JSP的网上书店系统
第一章 JAVA的网络功能与编程 1-1 JAVA语言简介 Java是一种简单易用.完全面向对象.具有平台无关性且安全可靠的主要面向Internet的开发工具.自从1995年正式问世以来,Java的快 ...
- mysql基于时间盲注_MYSQL基于时间的盲注详解
MYSQL基于时间的盲注 联合查询,报错注入,以及布尔盲注,都是基于攻击网站会回显消息,或者将错误信息返回在前端,或者会返回web页面的正确或错误 但是有时候网站关闭了错误回显或过滤了某些关键字,网页 ...
- 中西方对时间的差异_中西方时间观念差异_英文
<中西方时间观念差异_英文>由会员分享,可在线阅读,更多相关<中西方时间观念差异_英文(2页珍藏版)>请在人人文库网上搜索. 1.Compared with America b ...
- utc时间 单位换算_一些时间的概念与区分(UTC、GMT、LT、TAI等)
UT - 世界时 Universal Time 世界时是最早的时间标准.在1884年,国际上将1s确定为全年内每日平均长度的1/8.64×104.以此标准形成的时间系统,称为世界时,即 UT1. 19 ...
最新文章
- 浙江大学软件学院2020年保研上机模拟练习 7-3 Partial School Ranking
- 部署 DevStack - 每天5分钟玩转 OpenStack(17)
- 【安全漏洞】CVE-2021-1732 win32k漏洞分析
- 《Splunk智能运维实战》——3.6 制作每一主机不同请求方法数量的图表
- 调用微信和支付宝调三方接口扫描二维码?
- 中石油训练赛 - Historical Maths(二分)
- 如何一次性复制带有markdown/mathjax/latex的博客内容
- opensource项目_生日快乐,Opensource.com:9年
- 2017.10.28 排序 思考记录
- 文件服务器搭建_小型企业文件存储服务器的搭建四部曲
- LeetCode Assign Cookies
- java四种修饰符_java中的四种修饰符
- tsm2812通用定时器中断_通用定时器中断(TIM2)
- 在ubuntu安装使用miniconda
- MS SqL2000 数据库置疑状态的解决方法[转]
- 二叉排序树和二叉平衡树
- 笔记本onenote绘画快捷键_怎样设置onenote的快捷键
- 《objective-c程序设计》学习笔记
- 论本我、自我、超我对人工智能的启示
- 京东手机电商大数据统计平台搭建