当前位置: 首页 > news >正文

c++实现的一个定时器实例

/*
 * 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

小结: 所谓的定时器, 当时间到时执行某一个任务,是通过启动一个线程来实现的,
等待时是timer线程在等待,执行时是timer线程在执行.
调用线程和执行线程是不同的线程
*/

相关文章:

c++实现的一个定时器实例

/* * author: hjjdebug * date : 2023年 09月 23日 星期六 11:52:29 CST * description: 用std::thread 实现了一个定时器,深刻理解一下定时器是怎样工作的. * 参考Timer.h, Timer.cpp */ $ cat main.cpp #include "Timer.h" #include <unis…...

Python线程和进程

1、深度解析Python线程和进程 一篇文章带你深度解析Python线程和进程 - 知乎使用Python中的线程模块&#xff0c;能够同时运行程序的不同部分&#xff0c;并简化设计。如果你已经入门Python&#xff0c;并且想用线程来提升程序运行速度的话&#xff0c;希望这篇教程会对你有所帮…...

算法 寻找峰值-(二分查找+反向双指针)

牛客网: BM19 题目: 寻找数组峰值&#xff0c;可能多个返回任一个&#xff0c;每个值满足nums[i] ! nums[i 1] 思路: 双指针 left 0, right n-1, 相向而行&#xff0c;取中间位置mid, nums[mid]与nums[mid1]比较&#xff0c;如果nums[mid] < nums[mid1]&#xff0c;说明…...

【数据结构】—交换排序之快速排序究极详解,手把手带你从简单的冒泡排序升级到排序的难点{快速排序}(含C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;靴の花火—ヨルシカ 0:28━━━━━━️&#x1f49f;──────── 5:03 …...

【c#-Nuget 包“在此源中不可用”】 Nuget package “Not available in this source“

标题c#-Nuget 包“在此源中不可用”…但 VS 仍然知道它吗&#xff1f; (c# - Nuget package “Not available in this source”… but VS still knows about it?) 背景&#xff1a; 今日从公司svn 上拉取很久很久以前的代码&#xff0c;拉取下来200报错&#xff0c;进一步发…...

【数据结构】二叉树之堆的实现

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、二叉树的顺序结构 &#x1f4d2;1.1顺序存储 &#x1f4d2;1.2堆的性质…...

电工-三极管输入输出特性曲线讲解

三极管特性曲线是反映三极管各电极电压和电流之间相互关系的曲线&#xff0c;是用来描述晶体三极管工作特性曲线&#xff0c;常用的特性曲线有输入特性曲线和输出特性曲线。这里以下图所示的共发射极电路来分析三极管的特性曲线。 输入特性曲线 该曲线表示当e极与c极之间的电…...

深入解析容器与虚拟化:技术、对比与生态

深入解析容器与虚拟化&#xff1a;技术、对比与生态 文章目录 深入解析容器与虚拟化&#xff1a;技术、对比与生态容器和虚拟化的基本概念和原理容器的定义和特点虚拟化的定义和特点 容器使用场景容器和虚拟机的对比虚拟化技术的四个特点容器实现虚拟化的原理常见容器引擎和容器…...

制作游戏demo的心得

制作这个游戏demo出来的心得 https://www.bilibili.com/video/BV1cF411m7Dh/ 制作游戏demo的心得 制作游戏demo&#xff0c;主要是为了表现自己的技术&#xff0c;那就一门心思想着如何提高表现力就行了&#xff0c;在整体的画面渲染风格方面或许没有什么可选择的&#xff0c;…...

Web Tour Server窗口闪现

1.打开该文件所在位置 2.右击选择编辑&#xff0c;在最后一行加上pause&#xff0c;保存后重新打开Server窗口 3.重新打开后&#xff0c;若出现以下情况&#xff1a; 以管理员身份打开cmd命令行&#xff0c;输入命令netstat -aon|findstr “1080”&#xff0c;查看1080端口占用…...

Linux下的基本指令

目录 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09;&#xff1a; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a; 07.man指令&#xff08;重要&#xff09;&#xff1a; 08mv指令&#xff…...

随机数生成器代码HTML5

代码如下 <!DOCTYPE html> <html> <head> <title>随机数生成器</title> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <style> body { text-align: center; bac…...

正确理解redux Toolkits中createSlice的action.payload

使用redux Toolkits中的createSlice编写extraReducers经常看到使用action.payload来更新state状态值&#xff1a; 那么action.payload指的到底是什么&#xff1f; 让我们看看action的定义部分&#xff1a; 注意&#xff1a; action.payload不是上面ajax请求的返回内容&#x…...

YOLOv8快速复现 官网版本 ultralytics

YOLOV8环境安装教程.&#xff1a;https://www.bilibili.com/video/BV1dG4y1c7dH/ YOLOV8保姆级教学视频:https://www.bilibili.com/video/BV1qd4y1L7aX/ b站视频&#xff1a;https://www.bilibili.com/video/BV12p4y1c7UY/ 1 平台搭建YOLOv8 平台&#xff1a;https://www.a…...

Haproxy搭建 Web 群集实现负载均衡

目录 1 Haproxy 1.1 HAProxy的主要特性 1.2 HAProxy负载均衡策略 1.3 LVS、Nginx、HAproxy的区别 2 Haproxy搭建 Web 群集 2.1 haproxy 服务器部署 2.1.1 关闭防火墙 2.1.2 内核配置&#xff08;实验环境可有可无&#xff09; ​2.1.3 安装 Haproxy 2.1.4 Haproxy服务…...

Tessy 5.0.4

Tessy 5.0.4 Linux 2692407267qq.com&#xff0c;更多内容请见http://user.qzone.qq.com/2692407267/...

mybatis-plus根据指定条件批量更新

1.service实现类中 比如我这里只针对UserEntity&#xff0c;在UserServiceImpl下&#xff08;该实现类是继承了mybatis-plus的ServiceImpl的&#xff09;新增如下代码&#xff1a; public boolean updateBatchByQueryWrapper(Collection<UserEntity> entityList, Funct…...

虹科方案 | LIN/CAN总线汽车零部件测试方案

文章目录 摘要一、汽车零部件测试的重要性&#xff1f;二、虹科的测试仿真工具如何在汽车零部件测试展露头角&#xff1f;三、应用场景**应用场景1&#xff1a;方向盘开关的功能测试****应用场景2&#xff1a;各类型电机的控制测试****应用场景3&#xff1a;RGB氛围灯的功能测试…...

[solidity]合约调用合约

先写一个简单的合约将其部署&#xff0c;部署后的合约地址为&#xff1a;0xd9145CCE52D386f254917e481eB44e9943F39138 // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;contract A{string myname;function setName(string memory _name) public{myname_name;}functi…...

Vulnhub系列靶机---JANGOW 1.0.1

文章目录 网卡配置信息收集主机发现端口扫描 漏洞利用反弹Shell提权 靶机文档&#xff1a;JANGOW 1.0.1 下载地址&#xff1a;Download (Mirror) 难易程度&#xff1a;. 网卡配置 水果味儿 信息收集 主机发现 端口扫描 访问80端口 点击site目录 点击页面上方的一个选项&…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...