博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
毫秒级定时器模块的设计与实现
阅读量:5949 次
发布时间:2019-06-19

本文共 6049 字,大约阅读时间需要 20 分钟。

0、引言

  定时器在服务器的通信模块中会广泛使用到,通过定时器可以相应的高效实现业务逻辑。由于一般给出的定时器都是以秒作为最小单元来处理的,大部分场景能够满足要求,但在一些特殊场景需要实现更精确的定时任务,这时候,就有必要去构建一个毫秒级的定时管理模块。因而本文分享了一种定时器管理模块的实现方法,同时给出了相应的使用案例,希望对读者有一定的帮助。

1、毫秒级的时间类型

首先构建一个毫秒级的类型,并对相应的运算符进行了重载,具体代码示例如下:

#ifdef LINUX    #include 
#endif#ifdef IOS #include
#endif#ifdef WIN32 #include
#endifclass Time{private: struct timeval time_val;public: Time(); ~Time(); Time(const Time& other); Time(const struct timeval& timeVal); Time& operator=(const Time& other); Time& operator=(const struct timeval& timeVal); bool operator==(const Time& other); bool operator<(const Time& other); Time& operator+=(int val); time_t getSecond();}Time::Time(){ memset(time_val, 0, sizeof(struct timeval));}Time::Time(const Time& other){ time_val = other.time_val;}Time::Time(const struct timeval& timeVal){ time_val = timeVal;}Time& operator=(const Time& other){ time_val = other.time_val; return *this;}Time& operator=(const struct timeval& timeVal){ time_val = timeVal; return *this;}bool operator==(const Time& other){ if (time_val.tv_sec != other.time_val.tv_sec || time_val.tv_usec != other.time_val.tv_usec ) { return false; } return true;}bool operator<(const Time& other){ if (time_val.tv_sec < other.time_val.tv_sec) { return true; } else if (time_val.tv_sec == other.time_val.tv_sec) { if (time_val.tv_usec < other.time_val.tv_usec) { return true; } } return false;}Time& operator+=(int val){ time_val.tv_usec += val*1000; time_val.tv_sec += time_val.tv_usec/1000000; time_val.tv_usec = time_val.tv_usec % 1000000;}time_t getSecond(){ return time_val.tv_sec;}

 

2.定时任务的基类

  这可作为其他具体业务类型的基类,若该业务类型需要使用到定时器来执行定时任务,则应继承该类型。

class TimerObject{public:    TimerObject(){};    virtual ~TimerObject(){};    virtual void DoSomething(int time_id, Time time_val); //当定时触发时,执行该函数}

 

3.定时器节点的数据结构   

每个定时器对应一个定时器节点,相关参数有:每次定时的间隔时间、是否无限循环、触发的次数、具体执行定时任务的对象等

struct TimerNode{    int id;                //定时器节点的唯一标识    int interval;        //定时的时间间隔    Time startTime;        //开始定时的时间    bool isForever;        //是否无限循环    int totalCount;        //定时的总次数    int curCount;        //当前定时已触发的次数    TimerObject* obj;    //所触发定时任务的对象    TimerNode* preTimerNode;    //使定时器节点之间形成一个链表    TimerNode* nextTimerNode;    TimerNode()    {        id = 0;        interval = 0;        isForever = false;        totalCount = 0;        curCount = 0;        obj = NULL;        preTimerNode = NULL;        nextTimerNode = NULL;    }}

 

4.定时器管理的类型   

保存所有的定时器节点,并提供接口对相应的定时器节点进行操作,具体代码如下:

class TimerManager{private:    TimerNode* head;    map
TimerNodes; int currentTimerNum; TimerNode* nextCheckNode; public: TimerManager(); ~TimerManager(); int setTimer(TimerObject* obj, int interval, bool type=true, int total=0); void checkTimers(struct timeval& time); bool killTimer(int id); bool changeTimer(int id, int interval); }void checkTimers(struct timeval& time){ //遍历所有的定时器,并执行定时器相应的任务(DoSomething函数)}bool killTimer(int id){ map
::iterator iter = TimerNodes.find(id); if (iter == TimerNodes.end()) { return true; } TimerNode* delNode = iter->second; TimerNode* preNode = delNode->preTimerNode; TimerNode* nextNode = delNode->nextTimerNode; if (nextNode == NULL) { preNode->nextTimerNode = NULL; } else { preNode->nextTimerNode = nextNode; nextNode->preTimerNode = preNode; } TimerNodes.erase(iter); delete delNode; return true;}TimerManager(){ head = new TimerNode(); int currentTimerNum = 0;}int setTimer(TimerObject* obj, int interval, bool type, int total){ if(obj == NULL || total < 0 || (type == false && total == 0)) { return -1; } TimerNode* newNode = new TimerNode(); struct timeval now; getCurrentTime(&now); newNode->id = getTimerId(); newNode->startTime = Time(now); newNode->interval = interval; newNode->curCount = 0; newNode->totalCount = total; newNode->isForever = type; newNode->obj = obj; TimerNode* next = head->nextTimerNode; if (next) { head->nextTimerNode = newNode ; newNode->nextTimerNode = next ; newNode->preTimerNode = head ; next->preTimerNode = newNode ; } else { head->nextTimerNode = newNode; newNode->preTimerNode = head; } TimerNodes[newNode->id] = newNode; return newNode->id;}//取得一个空闲的id值int getTimerId(){}void getCurrentTime(struct timeval* now){#ifdef LINUX#ifdef IOS gettimeofday(now, NULL);#else struct timespec time_spec = {
0, 0}; int get_spec = clock_gettime(CLOCK_MONOTONIC, &time_spec); if(get_spec == 0) { now->tv_sec = time_spec.tv_sec; now->tv_usec = time_spec.tv_nsec/1000; } else { now->tv_sec = 0 ; now->tv_usec = 0 ; }#endif#endif}

 

5.示例,展现如何使用定时器   

  一方面应构建一个继承TimeObject的Task类型,并且实现基类中的虚函数。另一方面,在main函数中构建定时器管理对象,且启动定时任务。最后,构建一个循环不断的检测所有的定时器,判断是否有定时器触发,若有触发,则执行对应的任务函数。用例的代码实现如下:

class Task : public TimeObject{private:    int task_id;    static TimerManager* timeMng;    public:    Task()    {        task_id = -1;            }    ~Task()    {        if (task_id != -1)        {            timeMng->killTimer(task_id);        }    }    static void setTimeManager(TimerManager* timeM)    {        timeMng = timeM;    }    void start()    {        task_id = timeMng->setTimer(this, 10*1000, true, 0);    }        void DoSomething(int time_id, Time time_val)    {        if (task_id == time_id)        {            //执行定时任务        }    }    }int main(){    TimerManager* timeMng = new TimerManager();    Task* task = new Task();    Task::setTimeManager(timeMng);    task->start();        while(1)    {        struct timeval now;        getCurrentTime(&now);        timeMng->checkTimers(now);        sleep(1);    }        return 0;}

 

转载于:https://www.cnblogs.com/share-ideas/p/10896369.html

你可能感兴趣的文章
新手小白 python之路 Day3 (string 常用方法)
查看>>
soapUI的简单使用(webservice接口功能测试)
查看>>
框架 Hibernate
查看>>
python-while循环
查看>>
手机端上传图片及java后台接收和ajaxForm提交
查看>>
【MSDN 目录】C#编程指南、C#教程、ASP.NET参考、ASP.NET 4、.NET Framework类库
查看>>
jquery 怎么触发select的change事件
查看>>
angularjs指令(二)
查看>>
<气场>读书笔记
查看>>
领域驱动设计,构建简单的新闻系统,20分钟够吗?
查看>>
web安全问题分析与防御总结
查看>>
React 组件通信之 React context
查看>>
Linux下通过配置Crontab实现进程守护
查看>>
ios 打包上传Appstore 时报的错误 90101 90149
查看>>
密码概述
查看>>
jQuery的技巧01
查看>>
基于泛型实现的ibatis通用分页查询
查看>>
gopacket 使用
查看>>
AlertDialog对话框
查看>>
我的友情链接
查看>>