/*
* author: hjjdebug
* date : 2023年 09月 23日 星期六 11:52:29 CST
* description: 用std::thread 实现了一个定时器,深刻理解一下定时器是怎样工作的.
* 参考Timer.h, Timer.cpp
*/
$ cat main.cpp
#include "Timer.h"
#include <unistd.h>
void onTimeout()
{
std::cout << "timer Time out!" << std::endl;
}
int main()
{
Timer *m_timer;
m_timer = new Timer(1);
m_timer->start_recycle(onTimeout); // 传入回调,循环定时,每1秒执行一次回调
int loop=0;
//按Ctrl -c 可以退出
while(loop<5000)
{
sleep(1);
loop++;
}
m_timer->stop();
return 0;
}
$ cat Timer.h
#ifndef TIMER_H
#define TIMER_H
#include <stdio.h>
#include <unistd.h>
#include <functional>
#include <thread>
#include <iostream>
typedef std::function<void ()> CALL_BACK;
class Timer {
public:
Timer(unsigned seconds);
~Timer();
void start(CALL_BACK handle);
void start_recycle(CALL_BACK handle);
void stop();
private:
unsigned m_seconds = 0;
bool m_isAlive = false;
};
#endif
$ cat Timer.cpp
#include "Timer.h"
Timer::Timer(unsigned int seconds) {
m_seconds = seconds;
}
Timer::~Timer() {
}
void Timer::start(CALL_BACK handle)
{
auto timeThread = [=] // timer 线程代码
{
for (unsigned int i = 0; i< (m_seconds * 1000); i++)
{
if (m_isAlive)
{
usleep(1000); //睡眠1ms, 循环结束为m秒
}
else
{
return; //调用了stop, m_isAlive为false, 退出线程
}
}
if (m_isAlive)
{
handle(); //回调函数
}
stop(); // 循环结束即退出,一遍即可.
return;
};
if (!m_isAlive)
{
m_isAlive = true;
std::thread t(timeThread); //创建线程, 主线程代码
t.detach();
printf("main thread id: %d\n",gettid());
}
}
void Timer::start_recycle(CALL_BACK handle) {
auto timeThread = [=]
{
while (m_isAlive) // 线程在循环, 直到外部stop
{
//pthread_self() 头文件在pthread.h中,
//是pthread 库给每个进程中的每个线程定义的id,内核是不认识的
//数值很大, %ld, 我们看着也不方便
printf("timer pthread_self: %ld\n",pthread_self());
//gettid() 头文件在unistd.h中,由glibc来提供支持
printf("timer thread id: %d\n",gettid());
for (unsigned int i = 0; i < (m_seconds * 1000); i++)
{
if (m_isAlive)
{
usleep(1000);
}
else
{
return;
}
}
if (m_isAlive)
{
handle();
}
}
};
if (!m_isAlive)
{
m_isAlive = true;
std::thread t(timeThread);
t.detach();
printf("main thread id: %d\n",gettid());
}
}
void Timer::stop() {
m_isAlive = false;
}
/* 你可以用 ps -efT |grep "名称" 查看线程ID
也可以用 ps -efL |grep "名称" 查看线程ID
*/
执行结果
/*
执行程序, 打印了主线程id 11825 和线程id 11826
$ ./cpp_timer
main thread id: 11825
timer pthread_self: 139903798966016
timer thread id: 11826
timer Time out!
timer pthread_self: 139903798966016
timer thread id: 11826
用 ps -efT 或 ps -efL 也查到了cpp_timer 所有线程ID(11825,11826)
$ ps -efT |grep cpp_timer
hjj 11825 11825 9138 0 11:43 pts/1 00:00:00 ./cpp_timer
hjj 11825 11826 9138 1 11:43 pts/1 00:00:00 ./cpp_timer
hjj 11854 11854 10817 0 11:43 pts/3 00:00:00 grep --color=auto cpp_timer
hjj@hjj-u7090:~/test/cpp-timer$ ps -efL |grep cpp_timer
hjj 11825 9138 11825 0 2 11:43 pts/1 00:00:00 ./cpp_timer
hjj 11825 9138 11826 1 2 11:43 pts/1 00:00:00 ./cpp_timer
hjj 11866 10817 11866 0 1 11:44 pts/3 00:00:00 grep --color=auto cpp_timer文章来源:https://uudwc.com/A/aYNLG
小结: 所谓的定时器, 当时间到时执行某一个任务,是通过启动一个线程来实现的,
等待时是timer线程在等待,执行时是timer线程在执行.
调用线程和执行线程是不同的线程
*/文章来源地址https://uudwc.com/A/aYNLG