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

C++单例模式详解

目录

0. 前言

1. 懒汉式单例模式

1.1 最简单的单例模式

1.2 防止内存泄漏

1.2.1 智能指针的方法

1.2.2 静态嵌套的方法

1.3 保证线程安全

1.4 C++11版本的优雅解决方案

2. 饿汉式单例模式


0. 前言

起因是在程序中重复声明了一个单例模式的变量,后来程序怎么调都不对,最后发现变量是用单例模式,修改是全局的,所以决定好好梳理一下单例模式。

首先,为什么要用单例模式,就是因为我们希望一个类只有唯一一个实例,并且提供一个全局的访问点。从这个描述不难看出,这个实例应该是要static来修饰的。实际情况中,比如我们想申请一个内存池,程序都用这一块内存池,那么就可以单例模式来实现

1. 懒汉式单例模式

1.1 最简单的单例模式

先来看看最简单的单例模式怎么写,然后分析一下有什么问题。

#include <iostream>
using namespace std;// 最简单的单例模式
class Singleton{
public:// 获取实例的接口static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton(); // 使用new来创建一个新的实例对象} else {cout << "重复创建,返回已创建的实例。" << endl;}return instance;}
private:// 静态私有对象static Singleton* instance;// 构造函数一定要私有,外部无法直接访问构造函数Singleton() {cout << "运行构造函数" << endl;};~Singleton() {cout << "运行析构函数" << endl;};
};
// 要在类外进行初始化!!!
Singleton* Singleton::instance = nullptr;int main(){Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();return 0;
}

这里有两个点需要特别的注意:

  • 单例模式的类需要有一个静态私有的对象,是这个类的实例,且必须在类外进行初始化。
  • 获取实例的接口getInstance()函数式可以被访问和调用的,但是必须返回static类型的变量,实际上就是返回这个类的唯一实例
  • 补充下析构函数私有化的原因:保证只能在堆上new一个新的类对象。因为C++是一个静态绑定的语言。在编译过程中,所有的非虚函数调用都必须分析完成,即使是虚函数也需检查可访问性。当在栈上生成对象时,对象会自动析构,也就说析构函数必须可以访问。而堆上生成对象,由于析构时机由程序员控制,所以不一定需要析构函数。

按照上面的写法,基本上满足了单例模式的初衷,要一个只有一个实例的类。但是存在两个问题,一个是因为使用到了new进行创建,就需要人为进行delete的释放操作,否则就会造成内存泄漏。第二个是程序乍一看只会创建一块内存空间,但是如果考虑多线程,那么就有可能多个线程分别创建了多块内存空间的实例,与我们设计单例模式的初衷相违背。

1.2 防止内存泄漏

1.2.1 智能指针的方法

运行1.1的程序,结果为:

运行构造函数
重复创建,返回已创建的实例。

可以发现,并没有调用析构函数。这里,补充一下析构函数的作用:释放对象的使用资源,并销毁对象的非static数据成员。而我们定义的instance成员变量static的,所以无法直接使用析构函数进行释放。虽然事例的简单程序在运行完之后static变量会自动释放,但是在很多复杂的程序中,使用完instance却不释放是非常致命的会导致内存泄漏的问题。这里采用智能指针的方法,并借用智能指针的reset函数,定义一个销毁的成员函数,通过这个成员函数调用delete来释放我们创建的new内存,达到析构的目的。看看下面的实现。

#include <iostream>
#include <memory>
using namespace std;class Singleton{
public:// 公有接口获取唯一实例static shared_ptr<Singleton> getInstance() {if (instance == nullptr) {instance.reset(new Singleton(), destoryInstance);}else {cout << "重复创建,返回异创建的实例。" << endl;}return instance;}// 定义销毁的实例static void destoryInstance(Singleton* x) {cout << "自定义释放实例" << endl;delete x;}
private:Singleton() {cout << "运行构造函数。" << endl;};~Singleton() {cout << "运行析构函数。" << endl;};
private:// 静态私有对象static shared_ptr<Singleton> instance;
};// 初始化
shared_ptr<Singleton> Singleton::instance;int main(){shared_ptr<Singleton> s1 = Singleton::getInstance();shared_ptr<Singleton> s2 = Singleton::getInstance();return 0;
}

运行结果为:

运行构造函数。
重复创建,返回异创建的实例。
自定义释放实例
运行析构函数。

可以看到,我们通过智能指针,在使用完instance资源后调用了自定义的释放函数,即delete了new出来的空间,达到了运行析构函数的目的,防止了内存泄漏。

1.2.2 静态嵌套的方法

解决内存的泄漏的方法,总之是要把释放的过程先写好,不能靠用户每次自己释放。对于本次分享的例子,就是要把delete放进代码里。除了利用智能指针的释放函数来调用delete之外,也可以显式的调用delete函数,要单独嵌套一个类,把这个delete函数放进嵌套类的公有析构函数中。实现过程如下:

#include <iostream>
using namespace std;
class Singleton{
public:// 公有接口获取唯一实例static Singleton* getInstance() {if (instance == nullptr) {if (instance == nullptr) {instance = new Singleton();}}else {cout << "重复创建,返回已创建的实例。" << endl;}return instance;}
private:Singleton() {cout << "运行构造函数。" << endl;};~Singleton() {cout << "运行析构函数。" << endl;};// 定义一个删除器class Deleter {public:Deleter() {};~Deleter() {if (instance != nullptr) {cout << "删除器启动。" << endl;delete instance;instance = nullptr;}}};static Deleter deleter; // 删除器也是静态成员变量
private:// 静态私有对象static Singleton* instance;
};// 初始化
Singleton* Singleton::instance = nullptr;
Singleton::Deleter Singleton::deleter;int main()
{Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();return 0;
}

运行结果为:

运行构造函数。
重复创建,返回已创建的实例。
删除器启动。
运行析构函数。

1.3 保证线程安全

首先修改一下1.1中的程序,主要是增加一些打印,然后用多个线程创建Singleton的实例,看看是否每个线程都是访问的同一个内存地址。

#include <iostream>
#include <thread>
using namespace std;class Singleton{
public:// 获取实例的接口static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton(); // 使用new来创建一个新的实例对象cout << "创建地址为:" << instance << endl;} else {cout << "重复创建,返回已创建的实例。" << endl;}return instance;}
private:// 静态私有对象static Singleton* instance;// 构造函数一定要私有,外部无法直接访问构造函数Singleton() {cout << "运行构造函数" << endl;};~Singleton() {cout << "运行析构函数" << endl;};
};
// 要在类外进行初始化!!!
Singleton* Singleton::instance = nullptr;int main(){// Singleton* s1 = Singleton::getInstance();// Singleton* s2 = Singleton::getInstance();thread t1([] {Singleton* s1 = Singleton::getInstance();});thread t2([] {Singleton* s2 = Singleton::getInstance();});t1.join();t2.join();return 0;
}

运行结果如下:

运行构造函数
创建地址为:0x7f0988000b60
运行构造函数
创建地址为:0x7f0980000b60

可以发现,两个线程分别new出了一段内存空间(有一定几率是同一段,会报重复创建)。显然,这违背了我们单例模式的初衷。

解决方法是进行加锁,让一个线程先执行完,另一个线程才能获得new的权限。代码如下:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;class Singleton{
public:static Singleton* getInstance() {if (instance == nullptr) {lock_guard<mutex> l(mutex1); // 加锁保证线程安全if (instance == nullptr) {instance = new Singleton();cout << "创建地址为:" << instance << endl;}}else {cout << "重复创建,返回已创建的实例。" << endl;}return instance;}
private:static mutex mutex1;// 锁static Singleton* instance;Singleton() {cout << "运行构造函数" << endl;};~Singleton() {cout << "运行析构函数" << endl;};
};// 初始化
Singleton* Singleton::instance = nullptr;
mutex Singleton::mutex1;int main(){thread t1([](){Singleton* s1 = Singleton::getInstance();});thread t2([](){Singleton* s2 = Singleton::getInstance();});t1.join();t2.join();return 0;
}

运行结果为:

运行构造函数
创建地址为:0x7f90d4000b60
重复创建,返回已创建的实例。

加锁后,即使是多个线程,也只会申请一块内存空间。

1.4 C++11版本的优雅解决方案

上面只是为了将这个问题表述清楚,在C++11中,static变量是可以保证线程安全的,同时直接用static变量而不用new,就可以获得线程安全的且无内存泄漏的优雅写法,如下:

#include <iostream>
#include <thread>
using namespace std;
class Singleton{
public:// 公有接口获取唯一实例static Singleton* getInstance() {static Singleton instance;cout << "地址为:" << &instance << endl;return &instance;}private:Singleton() {cout << "运行构造函数" << endl;};~Singleton() {cout << "运行析构函数" << endl;};
};int main()
{thread t1([] {Singleton* s1 = Singleton::getInstance();});thread t2([] {Singleton* s2 = Singleton::getInstance();});t1.join();t2.join();return 0;
}

运行结果如下:

运行构造函数
地址为:0x55b7df269152
地址为:0x55b7df269152
运行析构函数

可以看到访问的内存地址一样,析构函数也正常的运行了。


2. 饿汉式单例模式

饿汉式和懒汉式的差别是,饿汉式提前进行了创建,而如果提前创建static变量,那么在程序开始前这个变量就创建好了,因此不存在线程不安全的问题,只需要保证不内存泄漏即可。用智能指针的方式实现代码如下:

#include <iostream>
#include <thread>
using namespace std;
class Singleton{
public:// 公有接口获取唯一实例static shared_ptr<Singleton> getInstance() {cout << "地址为:" << instance << endl;return instance;}// 定义销毁的实例static void destoryInstance(Singleton* x) {cout << "自定义释放实例" << endl;delete x;}private:Singleton() {cout << "运行构造函数" << endl;};~Singleton() {cout << "运行析构函数" << endl;};
private:// 静态私有对象static shared_ptr<Singleton> instance;
};// 初始化
shared_ptr<Singleton> Singleton::instance(new Singleton(), destoryInstance);int main(){thread t1([] {shared_ptr<Singleton> s1 = Singleton::getInstance();});thread t2([] {shared_ptr<Singleton> s2 = Singleton::getInstance();});t1.join();t2.join();return 0;
}

运行结果为:

运行构造函数。
地址为:0x55977895ceb0
地址为:0x55977895ceb0
自定义释放实例
运行析构函数。

也可以考虑优雅的写法:

#include <iostream>
#include <thread>
using namespace std;
class Singleton{
public:// 公有接口获取唯一实例static Singleton* getInstance() {static Singleton instance;cout << "地址为:" << &instance << endl;return &instance;}private:// 私有构造函数Singleton() {cout << "运行构造函数。" << endl;};// 私有析构函数~Singleton() {cout << "运行析构函数。" << endl;};
};int main(){thread t1([] {Singleton* s1 = Singleton::getInstance();});thread t2([] {Singleton* s2 = Singleton::getInstance();});t1.join();t2.join();return 0;
}

输出的结果为:

运行构造函数。
地址为:0x55aa7a895152
地址为:0x55aa7a895152
运行析构函数。

相关文章:

C++单例模式详解

目录 0. 前言 1. 懒汉式单例模式 1.1 最简单的单例模式 1.2 防止内存泄漏 1.2.1 智能指针的方法 1.2.2 静态嵌套的方法 1.3 保证线程安全 1.4 C11版本的优雅解决方案 2. 饿汉式单例模式 0. 前言 起因是在程序中重复声明了一个单例模式的变量&#xff0c;后来程序怎么调…...

LLM应用开发与落地:流式响应

一、背景 最近智能客服产品给到一个游戏客户那边&#xff0c;客户那边的客服负责人体验后认为我们产品回答的准确率是还是比较高的。同时&#xff0c;他反馈了几个需要改进的地方&#xff0c;其中一个就是机器人回复慢。机器人回复慢有很多原因&#xff0c;也有优化方式&#…...

神经网络 | 基于 CNN 模型实现土壤湿度预测

Hi&#xff0c;大家好&#xff0c;我是半亩花海。在现代农业和环境监测中&#xff0c;了解土壤湿度的变化对于作物生长和水资源管理至关重要。通过深度学习技术&#xff0c;特别是卷积神经网络&#xff0c;我们可以利用过去的土壤湿度数据来预测未来的湿度趋势。本文将使用 Pad…...

江科大STM32 终

目录 SPI协议10.1 SPI简介W25Q64简介10.3 SPI软件读写W25Q6410.4 SPI硬件外设读写W25Q64 BKP备份寄存器、PER电源控制器、RTC实时时钟11.0 Unix时间戳代码示例&#xff1a;读写备份寄存器BKP11.2 RTC实时时钟 十二、PWR电源控制12.1 PWR简介代码示例&#xff1a;修改主频12.3 串…...

《MySQL 简易速速上手小册》第10章:未来趋势和进阶资源(2024 最新版)

文章目录 10.1 MySQL 在云计算和容器化中的应用10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 部署 MySQL 到 Kubernetes10.1.3 拓展案例 1&#xff1a;在 AWS RDS 上部署 MySQL 实例10.1.4 拓展案例 2&#xff1a;使用 Docker 部署 MySQL 10.2 MySQL 和 NoSQL 的整合…...

Stable Diffusion 模型下载:GhostMix(幽灵混合)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 GhostMix 是绝对让你惊艳的模型&#xff0c;也是自己认为现在最强的2.5D模型。我认为模型的更新应该是基于现有的画面整体不大变的前提下&#xff0c;提高模型的成…...

django解决Table ‘xx‘ already exists的方法

1&#xff0c;首先看已存在的这个库表结构是什么样的&#xff0c;先让对应的model.py恢复到和他一样的字段 2&#xff0c;删除对应app下的migrations目录里面除__init__.py文件的其他所有文件 3&#xff0c;回到manage.py所在目录执行python manage.py makemigrations 4&#x…...

qt学习:arm摄像头+c调用v412框架驱动+qt调用v412框架驱动 显示摄像头画面

目录 跟内核进行数据通信的函数 编程步骤 c代码 头文件 打开摄像头文件 /dev/videox 获取当前主机上&#xff08;开发板&#xff09;摄像头列表信息 设置当前摄像头的画面格式 比如说 设置 采集图像的宽度为640 高度 480 在内核空间中&#xff0c;申请一个缓冲区队列…...

Linux 36.2@Jetson Orin Nano基础环境构建

Linux 36.2Jetson Orin Nano基础环境构建 1. 源由2. 步骤2.1 安装NVIDIA Jetson Linux 36.2系统2.2 必备软件安装2.3 基本远程环境2.3.1 远程ssh登录2.3.2 samba局域网2.3.3 VNC远程登录 2.4 开发环境安装 3. 总结 1. 源由 现在流行什么&#xff0c;也跟风来么一个一篇。当然&…...

牛客网SQL264:查询每个日期新用户的次日留存率

官网链接&#xff1a; 牛客每个人最近的登录日期(五)_牛客题霸_牛客网牛客每天有很多人登录&#xff0c;请你统计一下牛客每个日期新用户的次日留存率。 有一个登录(login。题目来自【牛客题霸】https://www.nowcoder.com/practice/ea0c56cd700344b590182aad03cc61b8?tpId82 …...

echarts 曲线图自定义提示框

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>曲线图</title><!-- 引入 ECharts 库 -->…...

幻兽帕鲁服务器怎么搭建?Palworld多人联机教程

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…...

DAY39: 动态规划不同路径问题62

Leetcode: 62 不同路径 机器人从(0 , 0) 位置出发&#xff0c;到(m - 1, n - 1)终点。 基本思路 1、确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] &#xff1a;表示从&#xff08;0 &#xff0c;0&#xff09;出发&#xff0c;到(i, j) 有dp[i][j]条…...

idea开发工具的简单使用与常见问题

1、配置git 选择左上角目录file->setting 打开&#xff0c;Version Control 目录下Git&#xff0c;选择git安装目录下的git.exe文件&#xff1b; 点击test&#xff0c;出现git版本&#xff0c;则表示git识别成功&#xff0c;点击右下角确认即可生效。 2、配置node.js 选…...

使用 WMI 查询安全软件信息

在这篇文章中&#xff0c;我们将详细介绍如何使用 Windows Management Instrumentation (WMI) API 来查询当前计算机上安装的安全软件的基本信息。我们将分析代码的各个部分&#xff0c;并解释每个步骤所涉及的技术和原理。 一、什么是 WMI&#xff1f; WMI 是 Windows Manag…...

创建TextMeshPro字体文件

相比于Unity的Text组件&#xff0c;TextMesh Pro提供了更强大的文本格式和布局控制&#xff0c;更高级的文本渲染技术&#xff0c;更灵活的文本样式和纹理支持&#xff0c;更好的性能以及更易于使用的优点。但unity自带TextMeshPro字体不支持中文。这里使用普通字体文件生成Tex…...

信创ARM架构QT应用开发环境搭建

Linux ARM架构QT应用开发环境搭建 前言交叉工具链Ubuntu上安装 32 位 ARM 交叉工具链Ubuntu上安装 64 位 ARM 交叉工具链 交叉编译 QT 库下载 QT 源码交叉编译 QT 源码 Qt Creator交叉编译配置配置 Qt Creator Kits创建一个测试项目 小结 前言 有没有碰到过这种情况&#xff1…...

使用SPM_batch进行批量跑脚本(matlab.m)

软件&#xff1a;spm8matlab2023bwin11 数据格式&#xff1a; F:\ASL\HC\CBF\HC_caishaoqing\CBF.nii F:\ASL\HC\CBF\HC_caishaoqing\T1.nii F:\ASL\HC\CBF\HC_wangdonga\CBF.nii F:\ASL\HC\CBF\HC_wangdonga\T1.nii clear spmdirD:\AnalysisApps\spm8; datadirF:\ASL\HC\CBF…...

力扣0124——二叉树的最大路径和

二叉树的最大路径和 难度&#xff1a;困难 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点…...

c# 字符串帮助类

public class StringHelper { #region 全角半角互相转换 /// <summary> /// 转全角的函数(SBC case) /// </summary> /// <param name"str">任意字符串</param> /// <returns>全…...

LabVIEW双光子荧光显微成像系统开发

双光子显微成像是一种高级荧光显微技术&#xff0c;广泛用于生物学和医学研究&#xff0c;尤其是用于活体组织的深层成像。在双光子成像过程中&#xff0c;振镜&#xff08;Galvo镜&#xff09;扮演了非常关键的角色&#xff0c;它负责精确控制激光束在样本上的扫描路径。以下是…...

Prim模板

通过代码探索Prim算法&#xff1a;最小生成树之旅 在计算机科学领域&#xff0c;图算法占据了至关重要的位置&#xff0c;尤其是在设计高效的网络&#xff08;无论是社交网络、计算机网络还是交通网&#xff09;时。在这些算法中&#xff0c;寻找最小生成树&#xff08;MST&am…...

CSS之盒子模型

盒子模型 01-选择器 结构伪类选择器 基本使用 作用&#xff1a;根据元素的结构关系查找元素。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IE…...

Linux系统安装(CentOS Vmware)

学习环境安装 VMware安装 VMware下载&安装 访问官网&#xff1a;https://www.vmware.com 在此处可以选择语言 点击China&#xff08;简体中文&#xff09; 点击产品&#xff0c;点击Workstation Pro 下滑&#xff0c;点击下载试用版 下滑找到Workstation 17 Pro for Wi…...

STM32 硬件随机数发生器(RNG)

STM32 硬件随机数发生器 文章目录 STM32 硬件随机数发生器前言第1章 随机数发生器简介1.1 RNG主要特性1.2.RNG应用 第2章 RNG原理框图第3章 RNG相关寄存器3.1 RNG 控制寄存器 (RNG_CR)3.2 RNG 状态寄存器 (RNG_SR)3.3 RNG 数据寄存器 (RNG_DR) 第3章 RNG代码部分第4章 STM32F1 …...

Window环境下使用go编译grpc最新教程

网上的grpc教程都或多或少有些老或者有些问题&#xff0c;导致最后执行生成文件时会报很多错。这里给出个人实践出可执行的编译命令与碰到的报错与解决方法。&#xff08;ps:本文代码按照煎鱼的教程编写&#xff1a;4.2 gRPC Client and Server - 跟煎鱼学 Go (gitbook.io)&…...

STM32——FLASH(1)简单介绍、分类、读写流程及注意事项

文章目录 FLASH的特点Nor flash和nand flashflash的读写flash 的存储单位 flash的读写过程 FLASH的特点 可擦写数据可修改可重写访问速度<ROM Nor flash和nand flash Nor flash 1、与SDRAM相似&#xff0c;用户可以直接运行装载到NORFLASH里面的代码&#xff0c;减少SRAM…...

MySQL的DML语言

DML&#xff1a;Data Manipulation Language&#xff08;数据操作语言&#xff09; DML语言用来对数据库中表的数据记录进行增、删、改操作。 一、添加数据命令 注意&#xff1a; 插入数据时&#xff0c;指定的字段顺序需要与值的顺序是一一对应的。 字符串和日期型数据应该包…...

Vivado-IP核

Vivado-IP核 主程序 timescale 1ns / 1ps ////module ip_clk_wiz(input sys_clk,input sys_rst_n,output clk_out1,output clk_out2,output clk_out3,output clk_out4,output locked);clk_wiz_0 instance_name(// Clock out ports.clk_out1(clk_out1), // output clk_out…...

品牌如何营造生活感氛围?媒介盒子分享

「生活感」简而言之是指人们对生活的感受和意义&#xff0c;它往往没有充斥在各种重要的场合和事件中&#xff0c;而是更隐藏在细碎平凡的生活场景中。在营销越来越同质化的当下&#xff0c;品牌应该如何打破常规模式&#xff0c;洞察消费情绪&#xff0c;找到更能打动消费者心…...

Java 学习和实践笔记(2)

今天的学习进度&#xff1a; 注册并下载安装好了Java 8&#xff0c;之后进行以下配置。 1&#xff09;path 是一个常见的环境变量&#xff0c;它告诉系统除了在当前的目标下妹寻找此程序外&#xff0c;还可以到path指定的目录下找。这句话是什么意思呢&#xff1f;以下举报例…...

Python:批量url链接保存为PDF

我的数据是先把url链接获取到存入excel中&#xff0c;后续对excel做的处理&#xff0c;各位也可以直接在程序中做处理&#xff0c;下面就是针对excel中的链接做批量处理 excel内容格式如下&#xff08;涉及具体数据做了隐藏&#xff09; 标题文件链接文件日期网页标题1http://…...

【LeetCode每日一题】525连续数组 303区域和检索(前缀和的基本概念和3个简单案例)

前缀和 // 构造prefix let prefix [0] arr.forEach(num > {prefix.push(prefix.at(-1) num); })如果想要计算某个区间 i 到 j 这个子数组的和时&#xff0c;可以根据 prefix[j1] - prefix[i] 获得。 例题1&#xff1a;303.区域和检索 - 数组不可变 给定一个整数数组 num…...

形态学算法应用之连通分量提取的python实现——图像处理

原理 连通分量提取是图像处理和计算机视觉中的一项基本任务&#xff0c;旨在识别图像中所有连通区域&#xff0c;并将它们作为独立对象处理。在二值图像中&#xff0c;连通分量通常指的是所有连接在一起的前景像素集合。这里的“连接”可以根据四连通或八连通的邻接关系来定义…...

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据 一、基于日志大小二、基于时间大小三、参数设置四、设置命令一、基于日志大小 "log.retention.bytes"是Apache Kafka中的一项配置参数,用于指定每个日志段文件的最大大小。当日志段文件的…...

pytest+allure批量执行测试用例

在 Pytest 中,可以使用装饰器 `@pytest.fixture` 来定义用例级别的前置和后置操作。下面是一个示例代码,演示了如何使用 Pytest 的前置和后置操作: ```python import pytest @pytest.fixture(scope="function") def setup_function(): print("Setup fu…...

SpringBoot和SpringMVC

目录 一、springboot项目 &#xff08;1&#xff09;创建springboot项目 &#xff08;2&#xff09;目录介绍 &#xff08;3&#xff09;项目启动 &#xff08;4&#xff09;运行一个程序 &#xff08;5&#xff09;通过其他方式创建和运行springboot项目 二、SpringMVC…...

免费搭建幻兽帕鲁服务器,白嫖阿里云游戏服务器

阿里云幻兽帕鲁服务器免费搭建方案&#xff0c;先在阿里云高校计划「云工开物」活动领取学生专享300元无门槛代金券&#xff0c;幻兽帕鲁专用服务器4核16G配置26元1个月、149元半年&#xff0c;直接使用这个无门槛300元代金券抵扣即可免费搭建幻兽帕鲁服务器。阿里云服务器网al…...

[技术杂谈]如何下载vscode历史版本

网站模板&#xff1a; https://code.visualstudio.com/updates/v1_85 如果你想下载1.84系列可以访问https://code.visualstudio.com/updates/v1_84​​​​​​ 然后看到&#xff1a; 选择对应版本下载即可&#xff0c;我是windows x64系统选择x64即可开始下载...

nginx slice模块的使用和源码分析

文章目录 1. 为什么需要ngx_http_slice_module2. 配置指令3. 加载模块4. 源码分析4.1 指令分析4.2 模块初始化4.3 slice模块的上下文4.2 $slice_range字段值获取4.3 http header过滤处理4.4 http body过滤处理5 测试和验证 1. 为什么需要ngx_http_slice_module 顾名思义&#…...

AI应用开发-python实现redis数据存储

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…...

2024年Java架构篇之设计模式

2024年Java实战面试题_java 5 年 面试-CSDN博客 1、单例模式...

搭建macOS开发环境-1:准备工作

请记住&#xff1a; 最重要的准备工作永远是&#xff1a;备份数据 !!! 通过图形界面检查 Mac 的 CPU 类型&#xff1a; 在搭载 Apple 芯片的 Mac 电脑上&#xff0c;“关于本机”会显示一个标有“芯片”的项目并跟有相应芯片的名称&#xff1a; 通过命令行检查Mac的CPU类型 …...

【Makefile语法 02】Makefile语法基础

目录 一、Makefile概述 二、Makefile变量 三、Makefile符号 一、Makefile格式 1. 基本格式&#xff1a; targets : prerequisties [tab键]command target&#xff1a;目标文件&#xff0c;可以是 OjectFile&#xff0c;也可以是执行文件&#xff0c;还可以是一个标签&…...

如何写一个其他人可以使用的GitHub Action

前言 在GitHub中&#xff0c;你肯定会使用GitHub Actions自动部署一个项目到GitHub Page上&#xff0c;在这个过程中总要使用workflows工作流&#xff0c;并在其中使用action&#xff0c;在这个使用的过程中&#xff0c;总会好奇怎么去写一个action呢&#xff0c;所以&#xff…...

排序算法的时间复杂度存在下界问题

对于几种常用的排序算法&#xff0c;无论是归并排序、快速排序、以及更加常见的冒泡排序等&#xff0c;这些排序算法的时间复杂度都是大于等于O(n*lg(n))的&#xff0c;而这些排序算法存在一个共同的行为&#xff0c;那就是这些算法在对元素进行排序的时候&#xff0c;都会进行…...

详解洛谷P2016 战略游戏/BZOJ0495. 树的最小点覆盖之战略游戏(贪心/树形DP)

Description Bob喜欢玩电脑游戏&#xff0c;特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。 他要建立一个古城堡&#xff0c;城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵&#xff0c;使得这些士兵能了望到所有的路。 注意&…...

解决The Tomcat connector configured to listen on port 8080 failed to start

问题 启动javar报错&#xff0c;提示如下 Description: The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured. Action: Verify the connector’s configuration, identify a…...

深度学习自然语言处理(NLP)模型BERT:从理论到Pytorch实战

文章目录 深度学习自然语言处理&#xff08;NLP&#xff09;模型BERT&#xff1a;从理论到Pytorch实战一、引言传统NLP技术概览规则和模式匹配基于统计的方法词嵌入和分布式表示循环神经网络&#xff08;RNN&#xff09;与长短时记忆网络&#xff08;LSTM&#xff09;Transform…...

C语言的循环结构

目录 前言 1.三种循环语句 1.while循环 2.for循环 2.1缺少表达式的情况 3.do while循环 2.break语句和continue语句 2.1在while循环中 2.2在for循环中 2.3在do while 循环中 3.循环的嵌套 4.go to语句 前言 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是…...