多线程中定时器的使用

QT : 多线程使用定时器 方法一: run()函数中初始化和start timer。 void MyThread::run() { timer = new QTimer(); connect(timer,SIGNAL(timeout()),this,SLOT(timerOut())); timer->start(1000); exec(); } void MyThread::timerOut() { qDebug()<<"Current Thread ID:"< 阅读详情

不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下。首先在linux编程中定时器函数有alarm()和setitimer(),alarm()可以提供一个基于秒的定时功能,而setitimer可以提供一个基于微妙的定时功能。

alarm()原型:
        #include <unistd.h>
        unsigned int alarm(unsigned int seconds);

这个函数在使用上很简单,第一次调用这个函数的时候是设置定时器的初值,下一次调用是重新设置这个值,并会返回上一次定时的剩余时间。

setitimer()原型:
        #include <sys/time.h>
        int setitimer(int which, const struct itimerval *value,struct itimerval *ovalue);

这个函数使用起来稍微有点说法,首先是第一个参数which的值,这个参数设置timer的计时策略,which有三种状态分别是:

ITIMER_REAL:使用系统时间来计数,时间为0时发出SIGALRM信号,这种定时能够得到一个精准的定时,当然这个定时是相对的,因为到了微秒级别我们的处理器本身就不够精确。

ITIMER_VIRTUAL:使用进程时间也就是进程分配到的时间片的时间来计数,时间为0是发出SIGVTALRM信号,这种定时显然不够准确,因为系统给进程分配时间片不由我们控制。

ITIMER_PROF:上面两种情况都能够触发

第二个参数参数value涉及到两个结构体:

struct itimerval {
                struct timeval it_interval;        /* next value */
                struct timeval it_value;        /* current value */
        };

struct timeval {
                long tv_sec;        /* seconds */
                long tv_usec;        /* microseconds */
        };

在结构体itimerval中it_value是定时器当前的值,it_interval是当it_value的为0后重新填充的值。而timeval结构体中的两个变量就简单了一个是秒一个是微秒。

上面是这两个定时函数的说明,这个函数使用本不是很难,可以说是很简单,但是碰到具体的应用的时候可能就遇到问题了,在多进程编程中使用一般不会碰到什么问题,这里说的这些问题主要体现在多线程编程中。比如下面这个程序:

#include <pthread.h>
        #include <signal.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/time.h>

void sig_handler(int signo)
        {
        alarm(2);
        printf("alarm signal\n");
        }

void *pthread_func()
        {
        alarm(2);
        while(1)
        {
                pause();
        }
        }

int main(int argc, char **argv)
        {
        pthread_t tid;
        int retval;

signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
                perror("pthread_create");
                exit(-1);
        }

while(1)
        {
                printf("main thread\n");
                sleep(10);
        }
        return 0;
        }
        这个程序的理想结果是:
        main thread
        alarm signal
        alarm signal
        alarm signal
        alarm signal
        alarm signal
        main thread
        可事实上并不是这样的,它的结果是:
        main pthread
        alarm signal
        main pthread
        alarm signal
        main pthread

为什么会出现这种情况呢?是因为发送给工作线程的信号中断的主线程的sleep,并且这个中情况只影响主线程而不会影响到其他的工作线程。我们怎么才能解决这种问题呢,最简单的方法是修改这个程序,修改这个线程主线程使用alarm,工作线程使用sleep。这样就能够达到我们的要求,但是有时候有不能简单的这样操作。所以我们就需要进一步的修改我们的程序。在这里我第一个想到的是使用signal(SIGALRM, SIG_IGN),可是这个是设置整个进程对这个信号的响应方式,经过测试也确实不能完成我期望的功能,那么怎么办呢?有这样一个函数pthread_sigmask,线程中的信号屏蔽,函数的原型及相关函数为:

#include <signal.h>
        int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
        函数中第一个参数how有三个值SIG_BLOCK、SIG_SETMASK和SIG_UNBLOCK这里我们是用第二个值SIG_SETMASK
        int sigemptyset(sigset_t *set); /*清除信号集合set*/
        int sigaddset(sigset_t *set, int signum); /*添加信号signum到信号集set中*/

 然后我们改造我们的程序为:
        #include <pthread.h>
        #include <signal.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/time.h>

void sig_handler(int signo)
        {
        alarm(2);
        printf("alarm signal\n");
        }

void *pthread_func()
        {
        alarm(2);
        while(1)
        {
        pause();
        }
        }

int main(int argc, char **argv)
        {
        pthread_t tid, tid_1;
        int retval;

signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
                perror("pthread_create");
                exit(-1);
        }

        sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        pthread_sigmask(SIG_SETMASK,&sigset,NULL);

while(1)
        {
                printf("main pthread\n");
                sleep(10);
        }
        return 0;
        }

这个时候我们就能够看到我们想要的结果了。

这里再附一个setitimer的使用范例:

#include <pthread.h>
        #include <signal.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <sys/time.h>

struct itimerval timerval;
        void sig_handler(int signo)
        {
        printf("alarm signal\n");
        }

void *pthread_func()
        {

setitimer(ITIMER_REAL, &timerval, NULL);
        while(1)
        {
                pause();
        }
        }

int main(int argc, char **argv)
        {
        pthread_t tid;
        int retval;
        timerval.it_interval.tv_sec = 2;
        timerval.it_interval.tv_usec = 0;
        timerval.it_value.tv_sec = 2;
        timerval.it_value.tv_usec = 0;

signal(SIGALRM, sig_handler);

        if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
        {
                perror("pthread_create");
                exit(-1);
        }

sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        pthread_sigmask(SIG_SETMASK,&sigset,NULL);

while(1)
        {
                printf("main thread\n");
                sleep(5);
        }
        return 0;
        }

个人的一些理解,有问题希望和大家交流!


 

多线程环境下本地数据存储与定时器的使用 本文详细探讨了在.NET中实现线程安全的本地数据存储的多种方法,包括ThreadLocal<T>、GetData与SetData方法,以及AsyncLocal<T>类。同时,介绍了.NET平台提供的定时器工具,包括通用的多线程定时器和特定于Windows的单线程定时器,并讨论了在.NET 6中引入的PeriodicTimer类如何简化异步循环操作。文章最后强调了不同定时器在精确度和线程安全方面的差异,并提供了示例代码。 阅读详情

相关推荐

从零到一:基于K375S主控的机械键盘优联无线化改造实战

本文详细记录了基于罗技K375S主控进行机械键盘优联无线化改造的全过程。从改造动机、核心原理与物料准备,到电路设计、PCB打样、焊接调试,逐步拆解了将优联技术集成到自定义机械键盘中的实战步骤。项目最终实现了低延迟、高稳定性且支持多设备连接的优联无线机械键盘,为DIY爱好者提供了高性价比的改造方案。

h0i1j2k3l的博客 601

Linux定时器

Linux定时器 本文为对优快云博主「songly_」的原创文章整理后著作的,遵循 CC 4.0 BY-SA 版权协议, 原文链接:https://blog.youkuaiyun.com/qq_35733751/article/details/82763230 struct:timerval //itimerval结构体中的成员类型为timeval struct timeval { time_t...

Dch19990825的博客 574

ANSYS Products19.1下载及安装教程

ANSYS Products19.1下载及安装破解教程 前言 ANSYS软件是美国ANSYS公司研制的大型通用有限元分析(FEA)软件,是世界范围内增长最快的计算机辅助工程(CAE)软件,能与多数计算机辅助设计(CAD,computer Aided design)软件接口,实现数据的共享和交换,如Creo, NASTRAN、Algor、I-DEAS、AutoCAD等。ansys project包括一整套的软件集合,它耦合了CFD模型的前处理,求解器和后处理所需要的相关软件,特比是它的workbench模块,

Mekeater的博客 2万+

线程中的定时器

定时器是一种控制任务延时调用,或者周期调用的技术。 定时器的实现方式 方式一:Timer publicvoidschedule​(TimerTasktask, longdelay, longperiod)。 task:处理的任务 delay:延迟时间 perriod:周期时间 package com.itheima.d7_timer; import java.util.Timer; import java.util.TimerTask; public class TimerDe...

weixin_51500673的博客 1045

带硬约束的物理信息神经网络(PINN with Hard Constraint)示例及代码

本文以一个案例介绍了带硬约束的物理信息神经网络的原理及实现步骤。

m0_72768523的博客 5357

复现基于PYNQ-Z2的手写数字识别卷积加速器设计

来源雪天鱼。

eachanm的博客 968

在线程中使用定时器

       在线程中使用  System.Windows.Forms.Timer 是不能触发 Tick 事件的,为什么?如何在线程中使用定时器呢?就看本文介绍。               一. System.Windows.Forms.Timer        System.Windows.Forms.Timer 要求要有UI 消息泵, 所以通常只在主线程上使用.        Syst...

weixin_34268610的博客 336

别再迷信Intel网卡了!用普通笔记本+TWINCAT3搭建EtherCAT主站的完整避坑实录

本文详细介绍了如何用普通笔记本和TWINCAT3搭建EtherCAT主站的完整避坑指南。通过破除必须使用Intel网卡的迷思,提供软件环境搭建、关键配置步骤、Wireshark抓包技巧及性能优化建议,帮助开发者低成本实现EtherCAT主站功能。

weixin_29305337的博客 705

25,Linux 信号

学习目标: -了解信号的分类与产生方式 -掌握不同情况下信号的产生方法 -掌握屏蔽、捕捉信号的方法 -熟练处理程序中产生的信号 -熟练掌握利用信号机制实现进程同步的方法 1.信号及信号来源 信号全称软中断信号,其本质是软件层次上对中断机制的一种模拟,用于提醒进程某件事情已经发生。 可以使用 kill -l 命令查看系统中的信号: 信号的编号从1开始,其中1~31号信号为常规信号,也就是早期信号模型中的不可靠信号; 34~64号信号为实时信号,是用于计算机底层开发中的信号。 .

m0_57908316的博客 414

“华为杯”研究生数学建模竞赛2017年-【华为杯】B题:面向下一代光通信的 VCSEL 激光器仿真模型

得出以下主要结论:在相同的偏置电流条件下,随着温度的升高,带宽的峰值向。在相同的温度下,随着电流的增大,带宽的峰值越小且曲线由波峰形状。方案,包括可能的数学公式,不同温度和偏置电流下的带宽响应曲线,并与问题。线,得出以下主要结论:在相同的偏置电流条件下,随着温度的升高,带宽的峰。在相同的温度下,随着电流的增大,带宽的峰值越小且曲线由波峰形状逐渐变得。得的激光器特性曲线和模型中仿真得到的特性曲线,之后,可以将两组曲线的差。说明的是,由于数值优化算法的成功与否很大程度上依赖于初始参数的猜测,参。

getusushu的博客 98

SAP生产订单技术性完成(TECO)操作指南与实战应用

生产订单技术关闭操作指南主要包括单笔和批量关闭两种方式,通过CO02/COHV事务码完成。

m0_47402127的博客 1932

定时器与多线程 SetTimer and Multi-Thread 每个线程独立使用一个定时器

生产者——消费者 模拟程序,需求如下:   将生产者和消费者模拟算法封装在一个动态链接库中,主程序调用相关函数。生产者放入产品和消费者取走产品的速度可调节。 分别用循环队列和栈实现。 一般模拟这个算法都是生产这,消费者各开一个线程,同步访问一个共享缓冲区。但是需求要求能调节速度,我的思路是在 每个线程里单独创建一个定时器,但是Windows下定时器特性是

hubinbin595959的专栏 2365

相机Camera日志分析之二十六:高通相机Camx 基于预览1帧的process_capture_request重要完整日志【见注释】

文章摘要:该日志记录了一个相机预览请求的处理流程。系统从HAL层开始处理capture_request,填充预览/拍照的buffer数据,并激活相关pipeline。流程涉及多个模块(ChiNodeWrapper、IFE、IPE等)的协同工作,包括获取ImageBuffer、设置请求映射关系、处理特征美颜参数(开关状态0,级别1)等关键步骤。日志详细展示了从请求下发到各节点处理的完整链路,包含多次buffer获取、fence设置及数据传递过程,最终完成预览帧数据的处理和保存(第0帧和第1帧)。该流程体现了移

517

linux 多线程中定时器的使用

在开发linux mjpg-streamer程序的时候,使用signal,奇怪的是程序竟然退出了。后来读了曹老师的文章,才解决了这个问题。 所以收录到自己的博客里。呵呵 多线程中定时器的使用41865100619 2010-10-14 19:47:29                                                             —— 曹忠明

ljq1203的专栏 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

qt中定时器和多线程的使用

定时器和多线程的使用: 注意:创建多线程需要加上新的线程类 1、创建一个新的线程类MyThread 头文件.h #ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread> class MyThread : public QThread { Q_OBJECT//注意这边,当需要用到信号和槽的时候,都需要加上...

Littlehero_121的博客 3435

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

定时器在多线程中的使用

在多线程中使用定时器必须开启Runloop,因为只有开启Runloop保持现成为活动状态,才能保持定时器不断执行 - (void)viewDidLoad { [super viewDidLoad]; [self performSelectorInBackground:@selector(testMultiThread) withObject:nil...

weixin_30467087的博客 171

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

在qt界面中通过定时器使用多线程的简单方法

最近在做ros平台下的项目,需要用到qt,之前对多线程完全不懂,上网找了一些博客看了一下,最终找到了一种简单使用多线程的方法。 具体可以参考下列博客 [Qt——线程与定时器](https://www.cnblogs.com/hellovenus/p/qt_thread_timer.html) 首先定义一个定时器和线程变量: QTimer *plantimer; QThread *planti...

EricLee23 1705

使用select实现多线程定时器

#include #include #include #include #include #include #include #include int set_timer_s(long u32Time) { struct timeval stuTime; int ret = 0; memset(&stuTime, 0, sizeof(struct

烟花易冷 4180

多线程相机模拟程序,使用定时器

一个多线程的模拟相机程序,涉及到线程的建立,图片的加载和显示,定时器的调用 lowCameraThread.h文件 #ifndef LOWCAMERATHREAD_H #define LOWCAMERATHREAD_H #include <QWidget> #include <QThread> #include <QImage> class lowCameraThread : public QThread { Q_OBJECT public: expli

qq_20189555的博客 280

.NET Framework中定时器timer的单线程与多线程使用讲解

如果你需要使用规律的时间间隔重复执行一些方法,最简单的方式是使用定时器(timer)。与下边的例子相比,定时器可以便捷、高效地使用内存和资源: ? 1 2 3 4 5 6 7 new Thread (delegate() {              while (enabled)              {         

hoiven的专栏 1万+
上一篇: 数据结构要点整理
下一篇: C++要点整理
xyk_code
博客等级 码龄15年 3粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值