定时器的实现步骤如下:
- 创建一个新线程
- 在那个线程里等待
- 等待指定时长后做任务
下面在一个程序中实现周期性定时任务执行与一次延时任务执行两种模式的定时器
Timer.cpp代码如下:
#ifndef _TIMER_H_
#define _TIMER_H_
#include <functional>
#include <chrono>
#include <thread>
#include <atomic>
#include <memory>
#include <mutex>
#include <condition_variable>
class Timer
{
public:
Timer() : _expired(true), _try_to_expire(false)
{}
Timer(const Timer& timer)
{
_expired = timer._expired.load();
_try_to_expire = timer._try_to_expire.load();
}
~Timer()
{
stop();
}
void start(int interval, std::function<void()> task)
{
// 如果启动,就不需要再启动了
if (_expired == false)
return;
// 启动异步定时器,启动线程并在该线程中等待
_expired = false;
std::thread([this, interval, task]() {
while (!_try_to_expire)
{
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
task();
}
{
// 计时器停止,更新过期的条件变量并唤醒主线程
std::lock_guard<std::mutex> locker(_mutex);
_expired = true;
_expired_cond.notify_one();
}
}).detach();
}
void startOnce(int delay, std::function<void()> task)
{
std::thread([delay, task]() {
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
task();
}).detach();
}
void stop()
{
if (_expired)
return;
if (_try_to_expire)
return;
_try_to_expire = true; //让定时器停止
{
std::unique_lock<std::mutex> locker(_mutex);
_expired_cond.wait(locker, [this] {return _expired == true; });
// 重置定时器
if (_expired == true)
_try_to_expire = false;
}
}
private:
std::atomic<bool> _expired; // 定时器停止状态
std::atomic<bool> _try_to_expire; // 定时器处于停止过程中
std::mutex _mutex;
std::condition_variable _expired_cond;
};
#endif // !_TIMER_H_
main.cpp代码如下:
#include <iostream>
#include "timer.hpp"
void OnceTimer()
{
std::cout << " trigger PeriodTimer " << std::endl;
}
void PeriodTimer(int nNum)
{
std::cout << " trigger OnceTimer, nNum: " << nNum << std::endl;
}
int main(int argc, char* argv[])
{
Timer timer;
//周期性执行的定时器
std::cout << " start period timer " << std::endl;
timer.start(1000, std::bind(PeriodTimer, 3));
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
timer.stop();
std::cout << " stop period timer " << std::endl;
// 只执行一次的定时器
std::cout << " start one shot timer " << std::endl;
timer.startOnce(1000, OnceTimer);
std::cout << " stop one shot timer " << std::endl;
//getchar();
return 0;
}
程序运行如下: