QT中QTimer的循环时间与槽函数执行时间以及在事件循环中触发,不同时间的结果分析

目录

当循环时间小于槽函数时间时: 

当循环间隔时间大于槽函数时间时:

当存在两个定时器器,其中一个还是间隔100ms,另一个间隔1000ms: 

当两个定时器的循环周期大于槽函数执行时间时

当在主程序中添加一个for循环后 

当在for循环中加上人为触发其他事件QCoreApplication::processEvents() 后

当把for循环放到子线程中运行时 

当在子线程中定义定时器时 


在使用QT过程中,新手在QTimer,多线程,信号槽不是很了解的时候,常常容易感觉有点乱,最近自己编写了几个案例,仔细研究了一下定时器,多线程,信号槽之间的相互关系。

个人总结:

线程是程序运行的基本单位,GUI编程中,主线程既是GUI线程,其他都是子线程,在创建子线程时,个人还是建议用movethread的方式。这种方式能将整个对象的生命周期都放置到一个独立的子线程中,对象的所有操作都将在子线程中完成。很符合线程的概念。

线程之间优先采用信号槽的方式通讯。保证线程安全的同时,也能保证一些需要时序控制的过程的安全可控运行。省去了线程同步的麻烦。

信号槽之所以能省去线程同步的麻烦,正是因为事件循环的作用,信号发送到子线程后,将按发送先后的顺序依次插入到子线程的事件队列中,当前面的事件处理完成后,依次执行后续事件。这个方式就能起到线程同步的作用。

而通过movethread的创建的子线程,当start的时候,默认是会开启一个子线程的事件循环。在非直接连接的信号槽绑定后,所有的信号都将在子线程的事件循环中依次完成。

而定时器的运行,也是在线程的事件循环中实现的,当timeout信号发出后,在创建该定时器的线程中将触发对应槽函数。也即在哪个线程创建,对应的timeout就在哪个线程的事件循环中执行。

线程中的程序的执行是串行的,所以信号槽,定时器触发都是按其信号的发送时间来顺序执行。

正是因为这样,当有多个定时器时,对应的槽函数的执行时间就一定得注意了,最好不要超过定时器的设置时间,因为一旦超过,定时器设置的定时时间将不是自己所设定的定时周期执行。很重要。

但是当在子线程中执行while循环时,由于线程是串行工作,没有退出while时,将阻塞事件循环中的其他所有事件。这时需要好好考虑子线程的作用,以及需要完成的工作都有哪些,以及相关动作是否适合放置在1个子线程中,是否还需要再次创建子线程,都是需要考虑的。在while 中放置一个QCoreApplication::processEvents();来人为触发事件。可以在一些场景下,保证while循环运行同时,响应其他所有事件,但是其后也要跟一个sleep指令,并且时间要合适,才能保证其他事件的及时响应。个人建议不要小于10ms的sleep时间。

当循环时间小于槽函数时间时: 

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest;timeTest.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });timeTest.start(100);return a.exec();
}

执行结果: 

结果分析:

QTimer 设置的循环时间小于槽函数的执行时间时,当循环时间结束时,并不会将槽函数中断,而是等槽函数运行结束后,直接再次进入,中间没有间隔时间。

当循环间隔时间大于槽函数时间时:

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest;timeTest.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });timeTest.start(7000);return a.exec();
}

 结果分析:

间隔时间都比较准。每次的间隔时间也不会存在累计误差。

当存在两个定时器器,其中一个还是间隔100ms,另一个间隔1000ms: 

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest.start(100);timeTest2.start(1000);return a.exec();
}

结果分析:

第一个100ms的定时器优先抢占触发事件,当执行完两个对应槽函数后,第二个1000ms的定时器才执行一次槽函数。 

100ms触发

1s-2s-3s-4s-5s-6s-1s-2s-3s-4s-5s-6s-第二个触发-

总结:在不能确定定时器槽函数执行时间时,如果还存在其他定时器,当第一个定时器执行超时时,将直接影响第二个定时器的执行周期。所以在这种应用中,尽量避免定时器的循环周期小于槽函数执行时长。

当两个定时器的循环周期大于槽函数执行时间时

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest2.start(1000);timeTest.start(7000);return a.exec();
}

结果分析:

当两个定时器在同一个线程中时,两个定时器是按单线程串行的方式执行,当其中一个定时器触发时,必须等待当前定时器执行完成后,才有可能执行另外的定时器,两个定时器的优先级感觉是随机的。这也就解释了为什么上个案例定时周期不稳定的原因。

当在主程序中添加一个for循环后 

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest2.start(1000);timeTest.start(7000);for (int i=0;i<100;++i){std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Main"<<i << std::endl;QThread::msleep(100);}return a.exec();
}

结论:两个定时器必须在for循环执行完成后,才能触发。再次 证明定时器在主线程中是以串行的方式执行。 当for循环没有结束时,定时器的timeout信号在线程中是阻塞的状况,是无法响应对应槽函数的。

当在for循环中加上人为触发其他事件QCoreApplication::processEvents() 后

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest2.start(1000);timeTest.start(7000);for (int i=0;i<100;++i){std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Main"<<i << std::endl;//适当的位置,插入一个processEvents,保证事件循环被处理QCoreApplication::processEvents();QThread::msleep(100);}return a.exec();
}

结论:当添加了 QCoreApplication::processEvents();后 在每次的for循环中都触发一次进程事件,保证timeout事件触发,是可行的。

当把for循环放到子线程中运行时 

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}class TestThread1:public QThread
{//Q_OBJECT
public:TestThread1() {};~TestThread1() {};void run(){for (int i=0;i<1000;++i){std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThread"<<i << std::endl;//适当的位置,插入一个processEvents,保证事件循环被处理//QCoreApplication::processEvents();QThread::msleep(100);}}};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest2.start(1000);timeTest.start(7000);TestThread1* test1{nullptr};test1 = new TestThread1;test1->start();//  for (int i=0;i<100;++i)//  {//      std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Main"<<i << std::endl;适当的位置,插入一个processEvents,保证事件循环被处理//QCoreApplication::processEvents();//      QThread::msleep(100);//  }return a.exec();
}

 结论:当在子线程中运行时,两个定时器能正常按预想的方式运行

当在子线程中定义定时器时 

#include <QtCore/QCoreApplication>
#include <QTimer>
#include <QThread>
#include <iostream>
#include <QObject>
#include <QTime>void timer1()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() <<"  6" << std::endl;
}void timer2()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Timer2" << std::endl;//QThread::msleep(1000);
}void timer3()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_1" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_2" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_3" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_4" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_5" << std::endl;QThread::msleep(1000);std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTime3_6" << std::endl;
}void timer4()
{std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThreadTimer4" << std::endl;//QThread::msleep(1000);
}class TestThread1:public QThread
{//Q_OBJECT
public:TestThread1() {};~TestThread1() {};void run(){QTimer time3;QTimer time4;time3.setTimerType(Qt::PreciseTimer);time4.setTimerType(Qt::PreciseTimer);QObject::connect(&time3, &QTimer::timeout, [=]() {timer3(); });QObject::connect(&time4, &QTimer::timeout, [=]() {timer4(); });time3.start(1000);time4.start(7000);for (int i=0;i<1000;++i){std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  subThread"<<i << std::endl;//适当的位置,插入一个processEvents,保证事件循环被处理QCoreApplication::processEvents();QThread::msleep(100);}}};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QTimer timeTest,timeTest2;timeTest.setTimerType(Qt::PreciseTimer);timeTest2.setTimerType(Qt::PreciseTimer);QObject::connect(&timeTest, &QTimer::timeout, [=]() {timer1(); });QObject::connect(&timeTest2, &QTimer::timeout, [=]() {timer2(); });timeTest2.start(1000);timeTest.start(7000);TestThread1* test1{nullptr};test1 = new TestThread1;test1->start();//  for (int i=0;i<100;++i)//  {//      std::cout << QTime::currentTime().toString("HH:mm:ss zzz").toStdString() << "  Main"<<i << std::endl;适当的位置,插入一个processEvents,保证事件循环被处理//QCoreApplication::processEvents();//      QThread::msleep(100);//  }return a.exec();
}

结论:当在子线程中定义定时器时,现象跟在主线程的现象一致。 

QCoreApplication::processEvents();
          QThread::msleep(100); 这暂停很关键,不同的暂停时间,对其他事件的影响很大,如果没有这个暂停时间,:processEvents()将无效,暂停时间越短,其他事件执行的几率就越小。在实际的应用中需要是个合适的延时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2845.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js - 对forEach()函数的一些理解

1&#xff0c;定义和用法 定义&#xff1a; forEach() 方法用于调用数组的每个元素&#xff0c;并将元素传递给回调函数。注意: forEach() 对于空数组是不会执行回调函数的。 用法&#xff1a; // 箭头函数 forEach((element) > { /* … */ }) forEach((element, index) &…

在uni-app中,如果data中的对象属性改变了,但是页面没有相应更新的情况,通常有以下几点需要注意:

1. 使用this.$set更新对象属性直接修改对象属性是无法触发页面更新的,需要使用this.$set方法: this.$set(this.obj, key, value) 2. 确保数据层级不太深如果对象层级过深,改变内层属性也可能无法触发更新。建议关键数据不要超过2层。 3. 使用深度 watcher可以在watch中用深度…

mcu 启动流程

MCU启动流程 MCU启动流程 MCU启动流程1 MCU的启动方式2 MCU程序启动执行过程3 启动过程的执行工作4 keil调式过程验证5 调试文件map 1 MCU的启动方式 单片机的启动方式&#xff0c;以stm32为例&#xff0c;如下&#xff1a; 不同的下载方式对应的不同的启动方式&#xff0c;st…

truffle 进行智能合约测试

本方法使用了可视化软件Ganache 前两步与不使用可视化工具的步骤是一样的&#xff08;有道云笔记&#xff09;&#xff0c;到第三步的时候需要注意&#xff1a; 在truffle插件下找到networks目录&#xff0c;提前打开Ganache软件 在Ganache中选择连接或者新建&#xff0c;我在…

如何学习Java集合框架? - 易智编译EaseEditing

要学习Java集合框架相关的技术和知识&#xff0c;可以按照以下步骤进行&#xff1a; 掌握Java基础知识&#xff1a; 在学习集合框架之前&#xff0c;确保你已经具备良好的Java编程基础&#xff0c;包括语法、面向对象编程&#xff08;OOP&#xff09;原理和常用的核心类库等。…

MySQL备份与还原/索引/视图

MySQL备份与还原/索引/视图练习 文章目录 一、备份与还原1、使用mysqldump命令备份数据库中的所有表2、备份booksDB数据库中的books表3、使用mysqldump备份booksDB和test数据库4、使用mysqldump备份服务器中的所有数据库5、使用mysql命令还原第二题导出的book表6、进入数据库使…

Gnina split_caffe_proto.py

1. 导入必要的模块&#xff1a;mmap、re、os、errno。 2. 获取当前脚本所在路径的绝对路径作为script_path。 3. 创建用于存放caffe.proto片段的目录结构。脚本尝试创建../docs/_includes/和../docs/_includes/proto/两个目录&#xff0c;若目录已存在则忽略&#xff0c;若创…

STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块 硬件平台 野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块 GY-39 是一款低成本&#xff0c;气压&#xff0c;温湿度&#xff0c;光强度传感器模块。工作电压 3-5v…

thinkphp 上传图片

public function upload_img(){// 读取图片资源// 存储路径$path "uploads/avatar";$file request()->file(background_img);// 存储图片$info $file->rule(uniqid)->move($path);// 存储成功if ($info) {//获取到上传图片的路径名称$name_img $path . …

linux查看ipynb文件

linux查看ipynb文件 使用jupyter查看 使用jupyter查看 安装 pip install jupyter添加配置好的环境到jupyter notebook的kernel中&#xff1a; python -m ipykernel install --user --name mmdet --display-name "mmdet"运行jupyter notebook &#xff08;在ipynb…

WebSocket理论和实战

一 WebSocket理论 1.1 什么是http请求 http链接分为短链接、长链接&#xff0c;短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接&#xff08;但是是单向的&#xff0c;只能从客户端向服务端发消息&#x…

pycharm import的类库修改后要重启问题的解决方法

通过将以下行添加到pycharm中的settings-> Build,Excecution,Deployment-> Console-> Python Console中&#xff0c;可以指示Pycharm在更改时自动重新加载模块&#xff1a; %load_ext autoreload %autoreload 2

ubuntu 设置系统时间矫正

1、安装ntpdate&#xff0c;同步标准时间 2、修改时区 3、在.profile文件中写入上面提示的信息&#xff0c;保存退出、更新配置文件或者重启生效 3.1、或者配合上面的cp那条命令&#xff0c;用下面的命令保存到底层 $ hwclock --systohc 4、重启之后&#xff0c;查看日期时间已…

中间件上云部署 rocketmq

中间件上云部署 rocketmq rocketmq部署一、rokectmq介绍二、rokectmq特性三、使用rocketmq理由四、rocketmq 核心概念五、rocketmq角色六、rocketmq集群部署方式七、rocketmq集群部署7.1 环境说明7.2 构建rocketmq镜像7.3 获取rocketmq-dashboard镜像7.4 rocketmq部署描述文件编…

linux安装mysql以及使用navicat连接mysql

目录 一、下载mysql 二、安装mysql 三、使用Navicat连接MySQL 四、常见问题 1、启动服务时报错 Failed to start mysql.service: Unit not found. 的解决方法。 2、登录过程出现&#xff1a;access denied for user’root’‘localhost’(using password:Yes) 的解决方…

Redis的缓存问题

说起Redis的缓存&#xff0c;我们知道前端发出的请求到后端&#xff0c;后端先从Redis中查询&#xff0c;如果查询到了则直接返回&#xff0c;如果Redis中未查询到&#xff0c;就去数据库中查询&#xff0c;如果数据库中存在&#xff0c;则返回结果并且更新到Redis缓存当中&…

Softmax函数

S o f t m a x Softmax Softmax 函数是一种常用的激活函数&#xff0c;通常用于多类别分类问题中。它的原理是将一个向量的元素转化为概率分布&#xff0c;使得每个元素的取值范围在0到1之间&#xff0c;并且所有元素的和为1。 S o f t m a x Softmax Softmax 函数的作用是将原…

<JAVA学习笔记>SpringBoot中的@Retryable重试注解

Retryable注解的功能顾名思义&#xff0c;即重试。它可以作用在方法上&#xff0c;当方法抛出指定的异常时&#xff0c;整个方法将会被重新执行。在使用时需要先在pom.xml中导入相关依赖&#xff0c;再在启动类中添加EnableRetry注释以开启重试功能&#xff0c;最后在相应的方法…

《遗留系统现代化》读书笔记(基础篇)

目录 为什么要对遗留系统进行现代化&#xff1f; 什么是遗留系统&#xff1f; 遗留系统的现代化价值 总结 遗留系统的四化建设 代码现代化 架构现代化 DevOps 现代化 团队结构现代化 总结 本文地址&#xff1a;《遗留系统现代化》读书笔记&#xff08;基础篇&#xff…

通讯录(纯C语言实现)

相信大家都有过通讯录&#xff0c;今天我来带大家实现以下最简单的通讯录&#xff0c;通过本篇文章&#xff0c;相信可以让大家对C语言有进一步的认识。 话不多说&#xff0c;我们先放函数的实现 #define _CRT_SECURE_NO_WARNINGS 1 #include "Contact.h"int Chea…