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

C++多线程编程——基于策略模式、单例模式和简单工厂模式的可扩展智能析构线程

1. thread对象的析构问题

在 C++ 多线程标准库中,创建 thread 对象后,必须在对象析构前决定是 detach 还是 join。若在 thread 对象销毁时仍未做出决策,程序将会终止。

然而,在创建 thread 对象后、调用 join 前的代码中,若程序抛出异常,就会跳过 join 的调用,进而导致程序终止。

因此,必须在异常捕获中也调用 join。

这无疑增加了编程的复杂性,因为每个相关位置都需要在正常流程中写一次 join,在异常捕获中再写一次。

下面的代码将演示这一情况:

#include <iostream>
#include <thread>using namespace std;void threadFunc()
{cout << "Hello from thread" << endl;
}int main()
{thread t(threadFunc);try{throw runtime_error("Something went wrong");}catch (...){t.join();throw;}t.join();
}

2. 一种简单的解决办法——RAII

一种简单的解决办法就是使用RAII思想,编写一个类来绑定一个thread对象,在类的析构函数中调用thread对象的join方法。

下面的代码展示了这一点:

#include <iostream>
#include <thread>using namespace std;class thread_guard
{
public:thread_guard(std::thread& t) : t_(t) {}~thread_guard(){if (t_.joinable()){t_.join();}}thread_guard(const thread_guard&) = delete;thread_guard& operator=(const thread_guard&) = delete;
private:thread& t_;
};void threadFunc()
{cout << "Thread function running..." << endl;
}int main()
{thread t(threadFunc);thread_guard g(t);return 0;
}

局部对象会自动被销毁,在销毁时thread_guard类对象的析构函数会自动调用thread类对象的join方法,从而保证thread不会异常终止。

但是这种方法太死板了,只会调用join方法。

我们可能希望自己选择detach或者join,也可能想要在thread对象销毁时做一些别的事情。

出于这种想法,本文提出了一种可扩展的智能析构线程,下面将对其进行介绍。

3. 可扩展的智能析构线程

首先,对于thread对象析构时不同的处理,这里使用了策略模式。通过提供不同的策略类,就可以扩展出不同的析构行为。

同时,目前实现的策略类没有自己的成员函数,所以采用了单例模式来创建,避免创建出大量相同的对象而造成内存浪费。

最后,通过简单工厂模式来获取策略类。

下面展示一下具体的代码:

#include <iostream>
#include <thread>using namespace std;class thread_destroy_strategy
{
public:virtual void destroy(thread& t)const = 0;virtual ~thread_destroy_strategy() = default;
};class join_strategy : public thread_destroy_strategy
{
public:static join_strategy* getInstance(){static join_strategy instance;return &instance;}void destroy(thread& t)const override{if (t.joinable()){t.join();cout << "Thread " << this_thread::get_id() << " joined" << endl;}}
};class detach_strategy : public thread_destroy_strategy
{
public:static detach_strategy* getInstance(){static detach_strategy instance;return &instance;}void destroy(thread& t)const override{if (t.joinable()){t.detach();cout << "Thread " << this_thread::get_id() << " detached" << endl;}}
};enum class EThreadStrategy
{JOIN,DETACH
};class strategyFactory
{
public:static thread_destroy_strategy* getStrategy(EThreadStrategy strategy){switch (strategy){case EThreadStrategy::JOIN:return join_strategy::getInstance();case EThreadStrategy::DETACH:return detach_strategy::getInstance();default:return nullptr;}}
};class auto_thread
{
public:template<typename F, typename... Args>auto_thread(F&& f, Args&&... args) : t(forward<F>(f), forward<Args>(args)...) {}~auto_thread(){thread_destroy_strategy* pStrategy = strategyFactory::getStrategy(strategy);if (pStrategy){pStrategy->destroy(t);}}auto_thread(const auto_thread&) = delete;auto_thread& operator=(const auto_thread&) = delete;public:void setStrategy(EThreadStrategy strategy_){strategy = strategy_;}
private:thread t;EThreadStrategy strategy = EThreadStrategy::JOIN;
};void threadFunc()
{cout << "Hello from thread" << endl;
}int main()
{auto_thread t(threadFunc);t.setStrategy(EThreadStrategy::JOIN); // 默认就是JOIN策略, 也可以设置为DETACH策略
}

策略类在destroy时打印了一下线程id。

运行结果如下图所示:

以上就是本文的全部内容

相关文章:

C++多线程编程——基于策略模式、单例模式和简单工厂模式的可扩展智能析构线程

1. thread对象的析构问题 在 C 多线程标准库中&#xff0c;创建 thread 对象后&#xff0c;必须在对象析构前决定是 detach 还是 join。若在 thread 对象销毁时仍未做出决策&#xff0c;程序将会终止。 然而&#xff0c;在创建 thread 对象后、调用 join 前的代码中&#xff…...

AI与SEO关键词的完美结合如何提升网站流量与排名策略

内容概要 在当今数字营销环境中&#xff0c;内容的成功不仅依赖于高质量的创作&#xff0c;还包括高效的关键词策略。AI与SEO关键词的结合&#xff0c;正是这一趋势的重要体现。 AI技术在SEO中的重要性 在数字营销领域&#xff0c;AI技术的引入为SEO策略带来了前所未有的变革。…...

保姆级教程Docker部署Kafka官方镜像

目录 一、安装Docker及可视化工具 二、单节点部署 1、创建挂载目录 2、运行Kafka容器 3、Compose运行Kafka容器 4、查看Kafka运行状态 三、集群部署 在Kafka2.8版本之前&#xff0c;Kafka是强依赖于Zookeeper中间件的&#xff0c;这本身就很不合理&#xff0c;中间件依赖…...

解析PHP文件路径相关常量

PHP文件路径相关常量包括以下几个常量&#xff1a; __FILE__&#xff1a;表示当前文件的绝对路径&#xff0c;包括文件名。 __DIR__&#xff1a;表示当前文件所在的目录的绝对路径&#xff0c;不包括文件名。 dirname(__FILE__)&#xff1a;等同于__DIR__&#xff0c;表示当前…...

WPS计算机二级•幻灯片的配色、美化与动画

听说这是目录哦 配色基础颜色语言❤️使用配色方案&#x1fa77;更改PPT的颜色&#x1f9e1;PPT动画添加的原则&#x1f49b;PPT绘图工具&#x1f49a;自定义设置动画&#x1f499;使用动画刷复制动画效果&#x1fa75;制作文字打字机效果&#x1f49c;能量站&#x1f61a; 配色…...

C#,shell32 + 调用控制面板项(.Cpl)实现“新建快捷方式对话框”(全网首发)

Made By 于子轩&#xff0c;2025.2.2 不管是使用System.IO命名空间下的File类来创建快捷方式文件&#xff0c;或是使用Windows Script Host对象创建快捷方式&#xff0c;亦或是使用Shell32对象创建快捷方式&#xff0c;都对用户很不友好&#xff0c;今天小编为大家带来一种全新…...

单纯信息展示的站点是否可以用UML建模

凌钦亮 More options Aug 7 2010, 10:36 am 现在社会上大量的网站需求都还只是用于单纯的企业信息展示&#xff0c;那此种网站是否有必要用UML 建模呢&#xff1f;业务用例图的一个个用例是用来卖的&#xff0c;但是他只有信息展示这个需 求&#xff0c;我是否在划分业务用例…...

FinRobot:一个使用大型语言模型的金融应用开源AI代理平台

“FinRobot: An Open-Source AI Agent Platform for Financial Applications using Large Language Models” 论文地址&#xff1a;https://arxiv.org/pdf/2405.14767 Github地址&#xff1a;https://github.com/AI4Finance-Foundation/FinRobot 摘要 在金融领域与AI社区间&a…...

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.19 线性代数核武器:BLAS/LAPACK深度集成

2.19 线性代数核武器&#xff1a;BLAS/LAPACK深度集成 目录 #mermaid-svg-yVixkwXWUEZuu02L {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-yVixkwXWUEZuu02L .error-icon{fill:#552222;}#mermaid-svg-yVixkwXWUEZ…...

开发板目录 /usr/lib/fonts/ 中的字体文件 msyh.ttc 的介绍【微软雅黑(Microsoft YaHei)】

本文是博文 https://blog.csdn.net/wenhao_ir/article/details/145433648 的延伸扩展。 本文是博文 https://blog.csdn.net/wenhao_ir/article/details/145433648 的延伸扩展。 问&#xff1a;运行 ls /usr/lib/fonts/ 发现有一个名叫 msyh.ttc 的字体文件&#xff0c;能介绍…...

Love Tester:探索爱情的深度与维度

爱情是什么&#xff1f;是相互帮助、耐心、理解、鼓励、保护、可靠和牺牲。Love Tester 通过先进的算法&#xff0c;分析名字的兼容性和关系的潜力&#xff0c;帮助你计算爱情匹配的准确性。 相互帮助&#xff1a;在伴侣遇到困难时伸出援手&#xff0c;这是爱情的体现。耐心&a…...

BFS(广度优先搜索)——搜索算法

BFS&#xff0c;也就是广度&#xff08;宽度&#xff09;优先搜索&#xff0c;二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS&#xff08;深度优先搜索&#xff09;。从字面意思也很好理解&#xff0c;DFS就是一条路走到黑&#xff0c;BFS则是一层一层地展开。…...

JVM 四虚拟机栈

虚拟机栈出现的背景 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的。优点是跨平台&#xff0c;指令集小&#xff0c;编译器容易实现&#xff0c;缺点是性能下降&#xff0c;实现同样的功能需要更多…...

【R语言】获取数据

R语言自带2种数据存储格式&#xff1a;*.RData和*.rds。 这两者的区别是&#xff1a;前者既可以存储数据&#xff0c;也可以存储当前工作空间中的所有变量&#xff0c;属于非标准化存储&#xff1b;后者仅用于存储单个R对象&#xff0c;且存储时可以创建标准化档案&#xff0c…...

Java BIO详解

一、简介 1.1 BIO概述 BIO&#xff08;Blocking I/O&#xff09;&#xff0c;即同步阻塞IO&#xff08;传统IO&#xff09;。 BIO 全称是 Blocking IO&#xff0c;同步阻塞式IO&#xff0c;是JDK1.4之前的传统IO模型&#xff0c;就是传统的 java.io 包下面的代码实现。 服务…...

统计满足条件的4位数(信息学奥赛一本通-1077)

【题目描述】 给定若干个四位数&#xff0c;求出其中满足以下条件的数的个数&#xff1a;个位数上的数字减去千位数上的数字&#xff0c;再减去百位数上的数字&#xff0c;再减去十位数上的数字的结果大于零。 【输入】 输入为两行&#xff0c;第一行为四位数的个数n&#xff0…...

北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评

在IT行业中&#xff0c;地理信息系统&#xff08;GIS&#xff09;是用于处理、分析和展示地理空间数据的重要工具&#xff0c;而ArcGIS则是GIS领域中的一款知名软件。本文将详细解析标题和描述中提及的知识点&#xff0c;并结合“门头沟区建筑物数据”这一标签&#xff0c;深入…...

Spring 面试题【每日20道】【其三】

1、Spring 中的 Profile 注解的作用是什么&#xff1f; 中等 Profile 注解在Spring框架中用于根据不同的环境配置文件&#xff08;profiles&#xff09;来激活或忽略某些Bean的注册。它允许开发者定义逻辑以区分不同环境下的bean定义&#xff0c;例如开发、测试和生产环境。 …...

FFmpeg(7.1版本)在Ubuntu18.04上的编译

一、从官网上下载FFmpeg源码 官网地址:Download FFmpeg 点击Download Source Code 下载源码到本地电脑上 二、解压包 tar -xvf ffmpeg-7.1.tar.xz 三、配置configure 1.准备工作 安装编译支持的软件 ① sudo apt-get install nasm //常用的汇编器,用于编译某些需要汇编…...

Apache Hudi数据湖技术应用在网络打车系统中的系统架构设计、软硬件配置、软件技术栈、具体实现流程和关键代码

网络打车系统利用Hudi数据湖技术成功地解决了其大规模数据处理和分析的难题&#xff0c;提高了数据处理效率和准确性&#xff0c;为公司的业务发展提供了有力的支持。 Apache Hudi数据湖技术的一个典型应用案例是网络打车系统的数据处理场景&#xff0c;具体如下&#xff1a; 大…...

Super IO插件终极指南:5分钟掌握Blender文件处理革命

Super IO插件终极指南&#xff1a;5分钟掌握Blender文件处理革命 【免费下载链接】super_io blender addon for copy paste import / export 项目地址: https://gitcode.com/gh_mirrors/su/super_io Super IO是一款彻底改变Blender工作流程的革命性插件&#xff0c;它通…...

APK Installer终极指南:如何在Windows上快速安装安卓应用?

APK Installer终极指南&#xff1a;如何在Windows上快速安装安卓应用&#xff1f; 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 还在为Windows上安装安卓应用而烦恼吗…...

Ask your GIT:AI驱动的代码仓库智能助手,一键解析与安装

1. 项目概述&#xff1a;一个为开发者“减负”的智能代码助手在GitHub、GitLab或者Bitbucket上发现一个看起来很有潜力的开源项目&#xff0c;是每个开发者的日常。但随之而来的&#xff0c;往往是长达十几甚至几十分钟的“阅读理解”时间&#xff1a;你得先通读冗长的README&a…...

FPGA生成SPWM的另一种思路:抛弃ROM,用DDS IP核与CORDIC算法实时生成正弦波

FPGA实时生成SPWM&#xff1a;基于DDS IP核与CORDIC算法的高效实现方案 在电力电子和电机控制领域&#xff0c;SPWM&#xff08;正弦脉宽调制&#xff09;技术因其优异的谐波特性和高效率而广受青睐。传统FPGA实现方案通常采用预存波形数据的ROM方法&#xff0c;虽然实现简单&a…...

德尔·考德威尔:从微波校准到计量标准,塑造现代精密测量的隐形基石

1. 一位计量学巨匠的遗产&#xff1a;从德尔考德威尔看精密测量的基石在电子工程与测试测量这个庞大而精密的领域里&#xff0c;我们常常关注的是最新的示波器带宽、最前沿的矢量网络分析技术&#xff0c;或是某个芯片的测试方案。然而&#xff0c;支撑起整个现代工业测量体系可…...

AI智能体自我进化:基于Diff机制的自动化优化实践

1. 项目概述&#xff1a;当AI智能体学会“自我进化”最近在开源社区里&#xff0c;一个名为agentdiff的项目引起了我的注意。它的核心想法非常有趣&#xff1a;让AI智能体&#xff08;Agent&#xff09;能够像我们人类一样&#xff0c;通过“反思”和“对比”来学习和进化。简单…...

从“能用”到“可靠”:基于SonarQube与Jenkins的Java代码质量防线构建实战

当测试覆盖率不再只是一串数字&#xff0c;而是合并代码前的“一票否决权” 1. 为什么你的“质量门禁”只是个摆设&#xff1f; 在很多团队的CI/CD流水线中&#xff0c;SonarQube的集成往往停留在“能跑就行”的阶段。流水线里确实有代码扫描这一步&#xff0c;日志里也打印出…...

从愚人节玩笑到工程实践:四个软硬件结合的创意项目技术拆解

1. 从愚人节玩笑到工程师的创意沙盘每年四月一日&#xff0c;总有些介于荒诞与现实之间的“产品”构想冒出来&#xff0c;在工程师社区里引发一阵会心一笑。但如果你仔细琢磨&#xff0c;会发现这些看似玩笑的点子&#xff0c;往往藏着一丝对技术边界、用户体验乃至市场需求的犀…...

从零构建FreeRTOS认知:核心概念与实战框架精讲

1. 认识FreeRTOS&#xff1a;嵌入式系统的"交通指挥官" 第一次接触FreeRTOS时&#xff0c;我盯着文档里那些"任务"、"队列"、"调度器"之类的术语发懵&#xff0c;就像刚拿到驾照就被扔进了早高峰的十字路口。后来才发现&#xff0c;这…...

Arm CoreSight TPIU-M调试技术详解与应用

1. Arm CoreSight TPIU-M技术深度解析在嵌入式系统开发中&#xff0c;调试和追踪功能是确保系统可靠性和性能优化的关键。作为Arm CoreSight调试架构的重要组成部分&#xff0c;TPIU-M&#xff08;Trace Port Interface Unit for Cortex-M&#xff09;为Cortex-M系列处理器提供…...