-
定时任务 - 二分定点法
-
简介: 有需要例如每日晚上十二点整点执行清除某些数据或者做定期信息更新时需要用到这种逻辑、该逻辑是我认为比较节省资源与精准的逻辑,若有觉得不对的地方可以补充一下
-
优点: 节省CPU损耗,不需要频繁检测当前时间
-
缺点: 若更改系统时间,有可能会导致当天定时无法触发
-
架构: 每次睡眠时间 (目标时间 - 当前时间)÷ 2
//C++ 11
#include <chrono>
#include <thread>
{
//时区 - cst时间戳是从1970-01-01 08:00:00开始计时
static const uint32_t nTimestampZone = 8 * 60 * 60;
//一整天所需要的秒数
static const uint64_t nWholeDaySec = 24 * 60 * 60;
//偏差范围 - 目标12:00:00 -> 实际允许 12:00:00 ~ 12:00:20
static const uint32_t nDeviationAreaSec = 20;
//目标时间
static const uint8_t nDstHour = 0;
static const uint8_t nDstMinute = 0;
static const uint8_t nDstSec = 0;
static const uint32_t nDstTimestampSec = (nDstHour * 60 * 60) + (nDstMinute * 60) + (nDstSec);
//今日是否已经执行过
bool bExecuted = false;
uint64_t nTime = 0;
while (true)
{
#ifdef __cplusplus > 201103L //C++11
//此处使用C++ 11(顺带了解C++11) - 可根据自己环境更改时间方法n
//获取系统时间 + 8:00:00 ; 因为cst时间戳是从1970-01-01 08:00:00开始计时的
//可以查找方法将 CST时间戳自动转换成UTC时间戳 但我没找到方法,因此只能写死的8:00:00
nTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) + nTimestampZone;
#else
//C语言中的time
nTime = time(nullptr) + nTimestampZone;
//std::localtime(&nTimet);
#endif
//实际偏差
int32_t nDeviation = nTime % nWholeDaySec - nDstTimestampSec;
//偏差在一定范围内
if (!bExecuted && nDeviation <= nDeviationAreaSec && nDeviation >= 0)
{
//执行相应处理
bExecuted = true;
/**
*
* * do something
*
**/
printf("Execute\n for Current Time [%02d:%02d:%02d]\n\n", nTime / 60 / 60, nTime / 60 % 60, nTime % 60);
continue;
}
else if (bExecuted && nDeviation <= nDeviationAreaSec && nDeviation >= 0)
{
//仍在区间范围内 则直接跳过
std::this_thread::sleep_for(std::chrono::seconds(1));
printf("Sleep Once in the Current Area \n");
continue;
}
else if (bExecuted && (nDeviation > nDeviationAreaSec || nDeviation < 0))
{
//经过区间范围之外
bExecuted = false;
continue;
}
static uint32_t nNeedSleep = 0;
nNeedSleep = (nDeviation > 0 ? nWholeDaySec - nDeviation : (abs(nDeviation))) / 2;
if (nNeedSleep == 1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
printf("Sleep once for [100 milliseconds]\n\n");
continue;
}
printf("Sleep once for [%d second]\n\n", nNeedSleep);
//睡眠偏差值
std::this_thread::sleep_for(std::chrono::seconds(nNeedSleep));
}
}