Redis时间任务精简版--定时器设计

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespa
摘要由CSDN通过智能技术生成

参考Redis的时间任务,完成定时任务的实现。测试通过

环境:

gcc (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


#include <iostream>

#include <algorithm>
#include <vector>
#include <string>
#include <sstream>
#include <cmath>
#include <list>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
using namespace std;


#define DEBUG(x) cout << '>' << #x << ':' << x << endl;
#define FOR(i,a,b) for(int i = (a);i < (b); ++i)


#define REDIS_HZ 100
#define run_with_period(_ms_) if (!(cronloops%((_ms_)/(1000/REDIS_HZ))))
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);




typedef struct aeTimeEvent {


    // 时间事件的唯一标识符
    long long id; /* time event identifier. */


    // 事件的到达时间
    long when_sec; /* seconds */
    long when_ms; /* milliseconds */


    // 事件处理函数
    aeTimeProc *timeProc;


    // 多路复用库的私有数据
    void *clientData;


    // 指向下个时间事件结构,形成链表
    struct aeTimeEvent *next;


} aeTimeEvent;




typedef struct aeEventLoop {
    // 目前已注册的最大描述符
    long long timeEventNextId;
    // 时间事件
    aeTimeEvent *timeEventHead;
    // 事件处理器的开关
} aeEventLoop;




/*
 * 取出当前时间的秒和毫秒,
 * 并分别将它们保存到 seconds 和 milliseconds 参数中
 */
static void aeGetTime(long *seconds, long *milliseconds)
{
    struct timeval tv;


    gettimeofday(&tv, NULL);
    *seconds = tv.tv_sec;
    *milliseconds = tv.tv_usec/1000;
}




/*
 * 为当前时间加上 milliseconds 秒。
 */
static void aeAddMillisecondsToNow(long long milliseconds, long *sec, long *ms) {
    long cur_sec, cur_ms, when_sec, when_ms;


    // 获取当前时间
    aeGetTime(&cur_sec, &cur_ms);


    // 计算增加 milliseconds 之后的秒数和毫秒数
    when_sec = cur_sec + milliseconds/1000;
    when_ms = cur_ms + milliseconds%1000;


    // 进位:
    // 如果 when_ms 大于等于 1000
    // 那么将 when_sec 增大一秒
    if (when_ms >= 1000) {
        when_sec ++;
        when_ms -= 1000;
    }
    *sec = when_sec;
    *ms = when_ms;
}




long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
        aeTimeProc *proc,void *clientData)
{
    // 更新时间计数器
    long long id = eventLoop->timeEventNextId++;
    aeTimeEvent *te;


    te = (aeTimeEvent*)malloc(sizeof(*te));
    if (te == NULL) return -1;


    te->id = id;


    // 设定处理事件的时间
    aeAddMillisecondsToNow(milliseconds,&te->when_sec,&te->when_ms);
    te->timeProc = proc;
    te->clientData = clientData;


    // 将新事件放入表头
    te->next = eventLoop->timeEventHead;
    eventLoop->timeEventHead = te;


    return id;
}




/*
 * 初始化事件处理器状态
 */
aeEventLoop *aeCreateEventLoop() {
    aeEventLoop *eventLoop;
    int i;


    // 创建事件状态结构
    if ((eventLoop = (aeEventLoop*)malloc(sizeof(*eventLoop))) == NULL) 
        return NULL;




    // 初始化时间事件结构
    eventLoop->timeEventHead = NULL;
    eventLoop->timeEventNextId = 0;


    /* Events with mask == AE_NONE are not set. So let's initialize the
     * vector with it. */
    return eventLoop;
}


/*
 * 删除事件处理器
 */
void aeDeleteEventLoop(aeEventLoop *eventLoop) {
    free(eventLoop);
}




/*
 * Time Process Function 
 * */
long long cronloops = 0;
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
    run_with_period(100) {
        cout << "this is 100 ms running" << endl;
    };
    run_with_period(1000) {
        cout << "this is 1000 ms running" << endl;
    };
    cronloops++;
    if(cronloops > 80000000)//define max
        cronloops = 0;
    return 1000/REDIS_HZ;
}


/* Process time events
 *
 * 处理所有已到达的时间事件
 */
static int processTimeEvents(aeEventLoop *eventLoop) {
    int processed = 0;
    aeTimeEvent *te;
    long long maxId;
    time_t now = time(NULL);


    te = eventLoop->timeEventHead;
    maxId = eventLoop->timeEventNextId-1;
    while(te) {
        long now_sec, now_ms;
        long long id;


        // 获取当前时间
        aeGetTime(&now_sec, &now_ms);
        /* DEBUG(now_sec); */
        /* DEBUG(te->when_sec); */
        /* DEBUG(now_ms); */
        /* DEBUG(te->when_ms); */


        // 如果当前时间等于或等于事件的执行时间,那么执行这个事件
        if (now_sec > te->when_sec ||
                (now_sec == te->when_sec && now_ms >= te->when_ms))
        {
            int retval;


            id = te->id;
            retval = te->timeProc(eventLoop, id, te->clientData);
            processed++;
            // 因为执行事件之后,事件列表可能已经被改变了
            // 因此需要将 te 放回表头,继续开始执行事件
            te = eventLoop->timeEventHead;
        } else {
            te = te->next;
        }
    }
    return processed;
}


int main(){
    aeEventLoop* el;
    el = aeCreateEventLoop();//initialize
    aeCreateTimeEvent(el, 100, serverCron, NULL);//register
    cout << "processing....." << endl;
    while(1)
        processTimeEvents(el); //process


    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
shiro-redis-spring-boot-starter是一个用于集成Apache Shiro和Redis的Spring Boot Starter项目。Apache Shiro是一个强大而灵活的Java安全框架,用于身份验证、授权和会话管理等安全功能。而Redis是一个高性能的内存数据库,其具有快速的数据存取能力和持久化支持。 shiro-redis-spring-boot-starter提供了一种简化和快速集成Shiro和Redis的方式,使得在Spring Boot应用中实现安全功能变得更加容易。通过使用该Starter,我们可以方便地将Shiro的会话管理功能存储到Redis中,从而支持分布式环境下的会话共享和管理。 使用shiro-redis-spring-boot-starter可以带来以下好处: 1. 分布式环境的会话共享:通过将Shiro的会话数据存储到Redis中,不同的应用节点可以共享同一个会话,从而实现分布式环境下的会话管理和跨节点的身份验证和授权。 2. 高可用性和性能:Redis作为一个高性能的内存数据库,具有出色的数据读写能力和持久化支持,可以提供可靠的会话存储和高性能的数据访问能力。 3. 简化配置和集成:shiro-redis-spring-boot-starter提供了封装好的配置和集成方式,减少了我们自己实现集成的复杂性和工作量。 总结来说,shiro-redis-spring-boot-starter为我们提供了一种简化和快速集成Shiro和Redis的方式,使得在Spring Boot应用中实现安全功能变得更加容易和高效。通过它,我们可以实现分布式环境下的会话共享和管理,提供高可用性和性能的数据存取能力,同时简化了配置和集成的复杂性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值