Qt中的单例模式
QT单例类管理信号和槽函数
- Chapter1 Qt中的单例模式
- 一、什么是单例模式?
- 二、Qt中单例模式的实现
- 2.1、静态成员变量
- 2.2、静态局部变量
- 2.3、Q_GLOBAL_STATIC 宏
- 实例2
- 三、使用场景
- 四、注意事项
- Chapter2 QT单例类管理信号和槽函数
- 一、创建单例类
- 二、主界面添加组件
- 三、组件代码绑定信号和槽
- 四、效果图
- 总结
- Chapter3 Qt单例模式的消息全局响应类($$$)
- 由来
- 代码
- GlobalMessageHelper.h文件
- globalmessagehelper.cpp文件
- DialogA.h/cpp文件
- DialogB.h/cpp文件
- DialogC.h/cpp文件
- DialogD.h/cpp文件
- main.cpp 文件
- 运行结果
- Chapter4 Qt全局信号通信
- 应用场景分析
- 功能实现1
- 功能实现2
- 功能实现3
- FAQ
Chapter1 Qt中的单例模式
原文链接:https://blog.csdn.net/baidu_18624493/article/details/130573407
一、什么是单例模式?
单例模式是一种创建型设计模式,用于确保类只有一个实例存在,并提供全局访问点以便于其他对象获取该实例。在单例模式中,类只能实例化一次,并提供了一个静态方法或全局访问点来获取该实例。这样可以确保在整个应用程序中只有一个实例存在,并且可以通过该实例进行操作和访问。
单例模式的特点包括:
单一实例:单例模式确保类只有一个实例存在。
全局访问点:通过静态方法或全局访问点获取单例对象,可以在任何地方访问该对象。
延迟初始化:单例对象通常在首次访问时才会被创建,实现了延迟初始化的效果。
限制对象创建:通过私有构造函数,限制其他类直接实例化单例对象。
单例模式在很多情况下都有用处,例如在需要共享资源、管理全局状态、控制资源访问等场景下可以使用单例模式。然而,过度使用单例模式可能导致代码的可测试性和可维护性下降,因此需要谨慎使用。
二、Qt中单例模式的实现
在Qt中,可以使用以下几种方式来实现单例模式。
2.1、静态成员变量
在类的私有静态成员变量中保存单例对象的指针,并提供一个静态方法来获取该对象。在静态方法中判断对象是否为空,如果为空则创建一个新的对象,否则返回已有的对象。这种方式保证了只有一个实例存在,并且在需要时进行延迟创建。
class Singleton {
private:static Singleton* instance;Singleton() {}public:static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}
};Singleton* Singleton::instance = nullptr;
使用时,通过静态方法getInstance()获取单例对象:
Singleton* singleton = Singleton::getInstance();
优点:
- 简单易用,容易理解和实现。
- 延迟初始化,只在需要时才创建单例对象。
- 在多线程环境下需要注意线程安全性。
缺点: - 在多线程环境下需要额外处理线程安全性,可能需要使用互斥锁等机制来保护访问。
- 对象的创建和销毁时机可能不受控制,可能存在资源管理的问题。
2.2、静态局部变量
在静态方法中使用静态局部变量保存单例对象的指针。静态局部变量在第一次调用时会被初始化,从而实现了延迟创建的效果。
class Singleton {
private:Singleton() {}public:static Singleton* getInstance() {static Singleton instance;return &instance;}
};
优点:
- 简洁,没有额外的静态成员变量。
- 延迟初始化,只在需要时才创建单例对象。
- 自动处理线程安全性,静态局部变量的初始化具有线程安全性。
缺点: - 在多线程环境下需要注意线程安全性。
- 对象的创建和销毁时机可能不受控制,可能存在资源管理的问题。
2.3、Q_GLOBAL_STATIC 宏
Qt 提供了 Q_GLOBAL_STATIC 宏,可以方便地定义全局的单例对象。这个宏使用了线程安全的延迟初始化机制,并提供了方便的访问方式。
class Singleton {
private:Singleton() {}public:static Singleton* instance() {static Q_GLOBAL_STATIC(Singleton, singleton);return singleton;}
};
实例2
#ifndef CONFIG_H
#define CONFIG_Hclass Config : public QObject {Q_OBJECTpublic:static Config *Instance();int doSomething();private:
};#endif // CONFIG_H#include "config.h"Q_GLOBAL_STATIC(Config, config)Config *Config::Instance() { return config(); }int Config::doSomething() {
}
优点:
- 简单易用,使用宏定义即可创建全局的单例对象。
- 延迟初始化,只在需要时才创建单例对象。
- 自动处理线程安全性,具有线程安全的延迟初始化机制。
缺点: - 对象的创建和销毁时机可能不受控制,可能存在资源管理的问题。
- 不适用于非全局范围的单例对象,只适用于全局单例对象的场景。
对于 Q_GLOBAL_STATIC 宏,Qt 提供了一种线程安全的延迟初始化机制。这是因为 Q_GLOBAL_STATIC 宏利用了 C++11 中的线程局部存储(thread-local storage)特性来实现。
线程局部存储是一种在每个线程中独立保存变量的机制,每个线程都有自己的变量实例,互不干扰。Q_GLOBAL_STATIC 宏利用这一特性,将单例对象的实例化和访问限制在每个线程的作用域内。
具体而言,Q_GLOBAL_STATIC 宏在使用时会根据 C++11 的线程局部存储特性,在每个线程中创建一个静态局部变量。每个线程都有自己的单例对象实例,并且线程之间的访问是互相隔离的,因此不会存在线程安全性问题。
在第一次访问该单例对象时,Q_GLOBAL_STATIC 宏会使用线程安全的方式进行初始化。在初始化过程中,会通过互斥锁等机制来保护对单例对象的访问,确保只有一个线程可以完成初始化过程。
通过使用线程局部存储和线程安全的初始化机制,Q_GLOBAL_STATIC 宏实现了线程安全的延迟初始化。这样,即使在多线程环境下同时访问单例对象,也能保证每个线程都能正确地获取到自己的单例对象实例,而不会引发竞争条件或其他线程安全性问题。
三、使用场景
单例模式在以下场景中通常被使用:
1、资源共享:当多个对象需要共享同一个资源时,可以使用单例模式确保只有一个实例存在,从而避免资源的重复创建和管理。
2、配置管理:单例模式可以用于管理应用程序的配置信息,例如日志配置、数据库连接配置等。通过单例模式,可以在整个应用程序中共享同一份配置数据,方便统一管理和访问。
3、对象缓存:某些需要频繁创建和销毁的对象,通过单例模式可以将这些对象缓存起来,提高性能和效率。例如线程池、数据库连接池等。
四、注意事项
在使用Qt单例模式时,需要注意以下几点:
1、线程安全性:如果在多线程环境下使用单例模式,需要确保对单例对象的访问是线程安全的。可以采用互斥锁(QMutex)或其他线程同步机制来保护对单例对象的访问。
2、生命周期管理:单例对象的生命周期通常延续整个应用程序的运行期间。确保在程序退出时,单例对象正确释放资源,避免内存泄漏。
3、耦合度控制:单例模式会引入全局状态,因此需要谨慎使用,避免过度依赖单例对象,导致代码的耦合度增加。应尽量将单例对象的使用限制在必要的范围内,遵循单一职责原则。
4、单元测试:单例对象的全局状态可能对代码的单元测试造成一定的影响。在进行单元测试时,需要注意单例对象的影响,并确保测试用例的独立性和可重复性。
5、可扩展性:在设计单例模式时,需要考虑到未来的扩展需求。如果将来需要创建多个类似的单例对象,需要设计一个可扩展的单例模式框架,以便灵活地管理和创建多个单例对象。
6、使用合适的方式:Qt提供了多种实现单例模式的方式,如静态成员变量、静态局部变量和Q_GLOBAL_STATIC宏等。根据实际需求选择合适的方式,权衡其优缺点。
Chapter2 QT单例类管理信号和槽函数
https://blog.csdn.net/qq_38491692/article/details/124623919
在QT当中,遇到主界面和多个组件槽函数绑定问题时,为了便于管理,我们可以通过单例类作为第三方来进行管理。
一、创建单例类
SignalInstance.h
#include <QObject>class SignalInstance:public QObject
{Q_OBJECT
public:static SignalInstance *GetInstance();static void Release();//释放static SignalInstance *signalinstance;signals:void send_to_windwostwo();void send_to_windwosone();
private:SignalInstance();
};
SignalInstance.cpp
#include "SignalInstance.h"
SignalInstance* SignalInstance::signalinstance = nullptr;//初始化对象
//释放单例对象
void SignalInstance::Release()
{if (signalinstance != NULL){delete signalinstance;signalinstance = NULL;}
}
SignalInstance::SignalInstance()
{}
//获得单例对象
SignalInstance* SignalInstance::GetInstance()
{if (signalinstance == NULL){signalinstance = new SignalInstance();}return signalinstance;
}
二、主界面添加组件
代码如下(示例):
#include <QObject>
#include<QVBoxLayout>
#include <QtWidgets/QWidget>
#include "SignalInstance.h"
#include"QtWidgets_1.h"
#include"QtWidgetsClass_2.h"
#include "instanse.h"
instanse::instanse(QMainWindow *parent): QMainWindow(parent)
{ui.setupUi(this);QVBoxLayout *lay = new QVBoxLayout(this);QtWidgets_1 *widget1 = new QtWidgets_1();lay->addWidget(widget1);ui.widget->setLayout(lay);QVBoxLayout *lay2 = new QVBoxLayout(this);QtWidgetsClass_2 *widget2 = new QtWidgetsClass_2();lay2->addWidget(widget2);ui.widget_2->setLayout(lay2);
}
三、组件代码绑定信号和槽
1.组件1
#pragma once#include <QWidget>
#include "ui_QtWidgets_1.h"class QtWidgets_1 : public QWidget
{Q_OBJECTpublic:QtWidgets_1(QWidget *parent = Q_NULLPTR);~QtWidgets_1();
private slots:void Show();
private:Ui::QtWidgets_1 ui;
};#include "QtWidgets_1.h"
#include"SignalInstance.h"
#include <QObject>
#include <QtWidgets/QWidget>
#pragma execution_character_set("utf-8")
QtWidgets_1::QtWidgets_1(QWidget *parent): QWidget(parent)
{ui.setupUi(this);connect(ui.pushButton, SIGNAL(clicked()), SignalInstance::GetInstance(), SIGNAL(send_to_windwostwo()));//绑定信号connect(SignalInstance::GetInstance(), SIGNAL(send_to_windwosone()), this, SLOT(Show()));//绑定槽函数
}QtWidgets_1::~QtWidgets_1()
{}
void QtWidgets_1::Show()
{ui.textEdit->setText("我是窗口2激活的");
}
2.组件2
#pragma once#include <QWidget>
#include "ui_QtWidgetsClass_2.h"class QtWidgetsClass_2 : public QWidget
{Q_OBJECTpublic:QtWidgetsClass_2(QWidget *parent = Q_NULLPTR);~QtWidgetsClass_2();
private slots:void Show();
private:Ui::QtWidgetsClass_2 ui;
};#include "QtWidgetsClass_2.h"
#include"SignalInstance.h"
#include <QObject>
#include <QtWidgets/QWidget>
#pragma execution_character_set("utf-8")
QtWidgetsClass_2::QtWidgetsClass_2(QWidget *parent): QWidget(parent)
{ui.setupUi(this);connect(SignalInstance::GetInstance(), SIGNAL(send_to_windwostwo()),this,SLOT(Show()));//绑定槽函数connect(ui.pushButton, SIGNAL(clicked()), SignalInstance::GetInstance(), SIGNAL(send_to_windwosone()));//绑定信号
}QtWidgetsClass_2::~QtWidgetsClass_2()
{
}
void QtWidgetsClass_2::Show()
{ui.textEdit->setText("我是窗口1激活的");
}
四、效果图
总结
本文案例使用组件较少,当项目较大时,比如上千个控件和布局,能有效的对信号和槽进行管理。
Chapter3 Qt单例模式的消息全局响应类($$$)
原文链接:https://blog.csdn.net/sunnyloves/article/details/125234467
由来
在飞扬青云大佬的文章Qt开发经验里的第82条写道:
Qt的信号槽机制非常牛逼,也是Qt的独特的核心功能之一,有时候我们在很多窗体中传递信号来实现更新或者处理,如果窗体层级比较多,比如窗体A的父类是窗体B,窗体B的父类是窗体C,窗体C有个子窗体D,如果窗体A一个信号要传递给窗体D,问题来了,必须先经过窗体B中转到窗体C再到窗体D才行,这样的话各种信号关联信号的connect会非常多而且管理起来比较乱,可以考虑增加一个全局的单例类AppEvent,公共的信号放这里,然后窗体A对应信号绑定到AppEvent,窗体D绑定AppEvent的信号到对应的槽函数即可,干净清爽整洁。
代码
于是想办法写了一个类GlobalMessageHelper 注意这个类用的是单例的设计模式。
验证的思路是写了4个窗口ABCD,其中A点击按钮弹窗D,B点击按钮弹窗C,C里点击按钮将其中LineEdit输入的内容传递到D里去。如果普通的传递路线应该是C->B->main->A->D(当然可以直接C->D,但是如果项目里很多这种跨窗口的消息直接传递,就会形成飞扬大佬提到的复杂情况)。用GlobalMessageHelper 类后,就可以通过它实现所有sender和receiver直接连接。效果可以看下一节。
GlobalMessageHelper.h文件
// GlobalMessageHelper h文件
#include <QWidget>
#include <QObject>
class GlobalMessageHelper : public QObject
{Q_OBJECT
public:~GlobalMessageHelper();static GlobalMessageHelper *getInstance();signals:void sendToAFromB(const QString &str);void sendToCFromD(const QString &str);
private:GlobalMessageHelper(QObject *parent = nullptr);static GlobalMessageHelper *gMessageHelper;
};
globalmessagehelper.cpp文件
// cpp文件
#include "globalmessagehelper.h"
GlobalMessageHelper *GlobalMessageHelper::gMessageHelper;GlobalMessageHelper::GlobalMessageHelper(QObject *parent) :QObject{parent}
{
}GlobalMessageHelper::~GlobalMessageHelper()
{
}GlobalMessageHelper *GlobalMessageHelper::getInstance()
{if (!GlobalMessageHelper::gMessageHelper)GlobalMessageHelper::gMessageHelper = new GlobalMessageHelper;return GlobalMessageHelper::gMessageHelper;
}
DialogA.h/cpp文件
// DialogA h文件
#include <QDialog>
#include <QWidget>
#include <QLineEdit>
class DialogA : public QDialog
{Q_OBJECT
public:DialogA(QDialog *parent = nullptr);
};// DialogA cpp文件
#include "dialoga.h"
#include "dialogd.h"
#include "globalmessagehelper.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QDebug>
DialogA::DialogA(QDialog *parent) : QDialog(parent)
{setWindowTitle("DialogA");setMinimumSize(QSize(300, 100));QVBoxLayout *lay = new QVBoxLayout;setLayout(lay);QPushButton *btn = new QPushButton("BTN");lay->addWidget(btn);connect(btn, &QPushButton::clicked, this,[&](){DialogD *dlg = new DialogD;dlg->show();});
}
DialogB.h/cpp文件
// DialogB h文件
#include <QDialog>
#include <QWidget>class DialogB : public QDialog
{Q_OBJECT
public:DialogB(QDialog *parent = nullptr);
};// DialogB cpp文件
#include "dialogb.h"
#include "dialogc.h"
#include <QVBoxLayout>
#include <QPushButton>
DialogB::DialogB(QDialog *parent) : QDialog(parent)
{setWindowTitle("DialogB");setMinimumSize(QSize(300, 100));QVBoxLayout *lay = new QVBoxLayout;setLayout(lay);QPushButton *btn = new QPushButton("BTN");lay->addWidget(btn);connect(btn, &QPushButton::clicked, this,[&](){DialogC *dlg = new DialogC;dlg->show();});
}
DialogC.h/cpp文件
// DialogC h文件
#include <QDialog>
#include <QWidget>
#include <QLineEdit>
class DialogC : public QDialog
{Q_OBJECT
public:DialogC(QDialog *parent = nullptr);private:QLineEdit *line = nullptr;QPushButton *btn = nullptr;
};// DialogC cpp文件
#include "dialogc.h"
#include "globalmessagehelper.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
DialogC::DialogC(QDialog *parent) : QDialog(parent)
{setWindowTitle("DialogC");setMinimumSize(QSize(300, 100));QVBoxLayout *lay = new QVBoxLayout;setLayout(lay);line = new QLineEdit;lay->addWidget(line);btn = new QPushButton("Send");lay->addWidget(btn);connect(btn, &QPushButton::clicked, this,[&](){emit GlobalMessageHelper::getInstance()->sendToAFromB(line->text());});
}
DialogD.h/cpp文件
// DialogD h文件
#include <QDialog>
#include <QWidget>
class QLineEdit;
class DialogD : public QDialog
{
public:DialogD();QLineEdit *line = nullptr;
};// DialogD cpp文件
#include "dialogd.h"
#include "globalmessagehelper.h"
#include <QLineEdit>
#include <QVBoxLayout>
DialogD::DialogD()
{setWindowTitle("DialogD");setMinimumSize(QSize(300, 100));QVBoxLayout *lay = new QVBoxLayout;setLayout(lay);line = new QLineEdit;lay->addWidget(line);connect(GlobalMessageHelper::getInstance(), &GlobalMessageHelper::sendToAFromB, this,[&](const QString &s){Q_ASSERT(GlobalMessageHelper::getInstance() != nullptr);line->setText(s);});
}
main.cpp 文件
// main.cpp 文件#include "globalmessagehelper.h"
#include "dialoga.h"
#include "dialogc.h"
#include "dialogb.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);DialogA dlgA;DialogB dlgB;dlgA.show();dlgB.show();return a.exec();
}
运行结果
Chapter4 Qt全局信号通信
原文链接:https://blog.csdn.net/u012790503/article/details/81950467
应用场景分析
Qt开发中经常会遇到作用域跨度比较大的对象间通信的场景,如果直接使用信号槽通过对象指针直接连接,首先需要将对象指针互相暴露出来,其中可能涉及到各种复杂的传递过程,导致程序混乱。一种解决方案是建立全局的信号中转站,实现全局范围内的便捷通信。
功能实现1
设现有对象A,需要将信号signalA()发送给对象B。
建立单例类class SIgnalStation。
在单例类中定义中转信号void transSignalA()。
在A的代码中,将A的信号与信号中转的信号连接:
A:: connect(this, SIGNAL(signalA()), SIgnalStation::instance(), SIGNAL(transSignalA()));
在对象B中连接中转信号:
B::connect(SignalStation::instance(), SIGNAL(transSignalA()), this, SLOT(…));
这样就实现了进程中任何对象间信号传递。
功能实现2
此种实现是用ID或字符串来实现对信号的索引,如下表所示:
通过这样的映射,可以实现更低的耦合,映射由一个管理器管理,如GlobalMsgMgr类。此类提供两个接口:
addEmit(const char *msg_id(信号ID), const char *signal(信号签名)):用于将本地信号绑定到信号ID上,本地信号触发时,自动触发所有连接到此信号ID上的槽。
addSlot(const char *msg_id(信号ID), const char *slot(槽签名)):用于将本地槽绑定到信号ID上,任意信号触发源触发此信号时,本地槽会被调用。
综上,
实现2比实现1的耦合程度更低,单从ID上看不出信号参数类型;好处是可以通过ID实现更松的耦合,甚至可以实现信号ID的比较运算。
实现1、实现2在触发信号时稍微麻烦一点,因为触发信号时,需要定义本地的信号。
功能实现3
参考:Qt使用信号槽模拟全局广播
这种方式在发送信号时较为简单,但是在定义和编译时略复杂。
个人建议,在简单应用下,使用功能实现1;在复杂应用下,使用功能实现2。
FAQ
为什么不用回调函数呢,因为信号槽可以很容易实现跨线程通信,回调函数跨线程调用需要处理竞争同步的问题。
相关文章:

Qt中的单例模式
QT单例类管理信号和槽函数 Chapter1 Qt中的单例模式一、什么是单例模式?二、Qt中单例模式的实现2.1、静态成员变量2.2、静态局部变量2.3、Q_GLOBAL_STATIC 宏实例2 三、使用场景四、注意事项 Chapter2 QT单例类管理信号和槽函数一、创建单例类二、主界面添加组件三、…...

ROS自学笔记十五:URDF工具
要使用工具之前,首先需要安装,安装命令: sudo apt install liburdfdom-tools 1.check_urdf 语法检查 在ROS中,你可以使用.check_urdf命令行工具来对URDF(Unified Robot Description Format)文件进行语法检查和验证。…...
Pytorch代码入门学习之分类任务(三):定义损失函数与优化器
一、定义损失函数 1.1 代码 criterion nn.CrossEntropyLoss() 1.2 损失函数简介 神经网络的学习通过某个指标表示目前的状态,然后以这个指标为基准,寻找最优的权重参数。神经网络以某个指标为线索寻找最优权重参数,该指标称为损失函数&am…...

【Linux】安装VMWare虚拟机(安装配置)和配置Windows Server 2012 R2(安装配置连接vm虚拟机)以及环境配置
前言: 一、操作系统简介 1、什么是操作系统 操作系统是一种软件,它管理计算机系统的硬件和软件资源,并提供给用户和应用程序接口,使它们能够与计算机系统交互和运行。操作系统负责调度和分配系统资源,例如处理器、内存…...

Python入口顶部人体检测统计进出人数
程序示例精选 Python入口顶部人体检测统计进出人数 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《Python入口顶部人体检测统计进出人数》编写代码,代码整洁,规则&a…...

移动端自动化-Appium元素定位
文章目录 Appium元素定位第一类:属性定位第二类:路径定位 常见问题理解appium server 和 appium inspector 以及 appium-python-client的关系 appium是跨平台的,支持OSX,Windows以及Linux系统。它允许测试人员在不同的平台&#x…...

menuconfig 图形化配置原理说明三
一. 简介 本文继续简单了解一下,uboot的图形化配置原理。具体了解 Kconfig语法。 之前文章了解了几个 Kconfig语法。地址如下: menuconfig 图形化配置原理说明二-CSDN博客 二. menuconfig 图形化配置之 Kconfig语法 1. config 条目 顶层 Kconfig …...

Ansible简介
环境 控制节点:Ubuntu 22.04Ansible 2.10.8管理节点:CentOS 8 组成 Ansible环境主要由三部分组成: 控制节点(Control node):安装Ansible的节点,在此节点上运行Ansible命令管理节点ÿ…...

Tomcat+nginx负载均衡和动静分离
Nginx实现负载均衡和动静分离的原理 Nginx实现负载均衡是通过反向代理实现Nginx服务器作为前端,Tomcat服务器作为后端,web页面请求由Nginx服务来进行转发。 但是不是把所有的web请求转发,而是将静态页面请求Ncinx服务器自己来处理,…...

全景环视AVM标定
目录 一、前言 二、鱼眼模型 三、标定流程 四、角点提取 4.1 亚像素坐标计算...

【JavaScript】leetcode链表相关题解
【JavaScript】leetcode链表相关题解 一、什么是链表?二、Javascript中的链表三、leetcode相关链表2.两数相加237.删除链表中的节点206.反转链表 💎个人主页: 阿选不出来 💎个人简介: 大三学生,热爱Web前端,随机掉落学…...

洞察运营机会的数据分析利器
这套分析方法包括5个分析工具: 用“描述性统计”来快速了解数据的整体特点。用“变化分析”来寻找数据的问题和突破口。用“指标体系”来深度洞察变化背后的原因。用“相关性分析”来精确判断原因的影响程度。用“趋势预测”来科学预测未来数据的走势,...

使用Python实现文字的声音播放
winsound 是 Python 的一个内置模块,它提供了访问 Windows 操作系统的声音播放功能的接口。这个模块可以用来播放简单的声音,例如提示音或者短促的音效。 # Author : 小红牛 # 微信公众号:WdPython import win32com.client import winsound#…...

gulp自动化构建
什么是Gulp? Gulp是一种前端开发过程中广泛使用的自动化构建工具,它是基于Node.js构建的,能够极大地提高开发效率和代码质量。Gulp的主要功能包括文件的压缩、合并、重命名等,同时它也支持文件监听和浏览器自动刷新等功能。使用Gulp&#x…...

java时间解析生成定时Cron表达式工具类
Cron表达式工具类CronUtil 构建Cron表达式 /****方法摘要:构建Cron表达式*param taskScheduleModel*return String*/public static String createCronExpression(TaskScheduleModel taskScheduleModel){StringBuffer cronExp new StringBuffer("");if(…...

JavaEE 网络原理——TCP的工作机制(末篇 其余TCP特点)
文章目录 一、滑动窗口二、流量控制三、拥堵控制四、延时应答五、捎带应答六、面向字节流七、异常情况八、总结 其余相关文章: JavaEE 网络原理——TCP的工作机制(中篇 三次握手和四次挥手) 本篇文章衔接的是前面两篇文章的内容,在这里继续解释 TCP 的内…...

【软件测试】了解JUnit单元测试框架常用注解
目录 1、认识JUnit 2、Junit中常见的注解 1、Test 2、Disabled 3、BeforeAll和AfterAll 4、BeforeEach和AfterEach 5、 ParameterizedTest:参数化 6、order 3、断言 1、断言相等【Assertions.assertEquals(预期,比较值)】;相等测试通…...

【广州华锐互动】三维全景3D消防科普展馆
在我们的日常生活中,火灾安全是一个不容忽视的重要问题。然而,由于缺乏对火灾的了解和应对技巧,许多人在面对火灾时往往感到无助和恐慌。为了解决这个问题,广州华锐互动开发了三维全景3D消防科普展馆,它是一个以虚拟现…...

某大型车企:加强汽车应用安全防护,开创智能网联汽车新篇章
某车企是安徽省最大的整车制造企业,致力于为全球消费者带来高品质汽车产品和服务体验,是国内最早突破百万销量的汽车自主品牌。该车企利用数字技术推动供应链网络的新型互动,加快数字化转型,持续进行场景创新、生态创新…...

LLVM学习笔记(50)
4.1.4. DAG合并与合法化 来自SelectionDAGBuilder的SelectionDAG输出还不能进行指令选择,必须通过额外的转换——显示在上图。在指令选择前应用的遍序列如下: 匹配一组节点,在有利时使用更简单的构造来替换它们,DAG合并遍优化Se…...

rpc入门笔记0x01
syntax "proto3"; // 这是个proto3的文件message HelloRequest{ // 创建数据对象string name 1; // name表示名称,编号是1 }生成python文件 安装grpcio和grpcio-tools库 pip install grpcio #安装grpc pip install grpcio-tools #安装grpc tools生成…...

web - Tomcat服务器
文章目录 目录 文章目录 前言 一 . CS和BS的异同 二 . 什么是Tomcat 二 . Tomcat安装 四 . Tomcat目录结构 bin目录: 用于存放二进制的可执行文件 config目录 server.xml:配置整个服务器信息。例如修改端口号。默认HTTP请求的端口号是:8080 lib目录 log…...

后端接口返回常见的状态码
2开头 (请求成功)表示成功处理了请求的状态代码 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 201 (已创建) 请求成功并且服务器创建了新的资源。 202 …...

50.MongoDB快速入门实战
MongoDB概念 MongoDB是一个文档数据库(以 JSON 为数据模型),由C语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。 原则上 Oracle 和 MySQL 能做的事情,MongoDB 都能做(包括 ACID 事务&#x…...

一款功能强大的音乐曲谱软件Guitar Pro 8 .1.1for Mac 中文破解版
Guitar Pro 8 .1.1for Mac 中文破解版是一款功能强大的音乐曲谱软件,非常适合学习如何玩,改进技巧,重现喜爱的歌曲或陪伴自己。可以帮助我们进行吉他的学习、绘谱与创作,它包含了几乎所有的吉他现有指法及音色,在做弹拨…...

图论基础和表示
一、概念及其介绍 图论(Graph Theory)是离散数学的一个分支,是一门研究图(Graph)的学问。 图是用来对对象之间的成对关系建模的数学结构,由"节点"或"顶点"(Vertex)以及连接这些顶点的"边"(Edge&a…...

STM32 音频ADC转wav格式
STM32 音频ADC DAC测试方法_stm32 adc 音频-CSDN博客 STM32--vs1053 WAV录音实现(保存在SD卡)_vs1053 多字节读取-CSDN博客 单片机内部AD实现录音wav文件_adc语音信号采样_天外飞仙CUG的博客-CSDN博客 PCM编码格式_pcm格式-CSDN博客 用ADC编码PCM数据…...

面试中经常问道的问题二
深入理解前端跨域方法和原理 前言 受浏览器同源策略的限制,本域的js不能操作其他域的页面对象(比如DOM)。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。所以我们要通过一些方法使本域的js能够操作其他域的页面对象或者使…...

SQL UPDATE 语句(更新表中的记录)
SQL UPDATE 语句 UPDATE 语句用于更新表中已存在的记录。 还可以使用AND或OR运算符组合多个条件。 SQL UPDATE 语法 具有WHERE子句的UPDATE查询的基本语法如下所示: UPDATE table_name SET column1 value1, column2 value2, ... WHERE conditi…...

js节流和防抖
节流(throttle)和防抖(debounce)是为了解决函数频繁触发而引发性能问题的两种优化方法。 节流: 指定一个时间间隔,在时间间隔内只执行一次函数,即在一段时间内,多次触发函数只执行一…...