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 多线程标准库中,创建 thread 对象后,必须在对象析构前决定是 detach 还是 join。若在 thread 对象销毁时仍未做出决策,程序将会终止。 然而,在创建 thread 对象后、调用 join 前的代码中ÿ…...
AI与SEO关键词的完美结合如何提升网站流量与排名策略
内容概要 在当今数字营销环境中,内容的成功不仅依赖于高质量的创作,还包括高效的关键词策略。AI与SEO关键词的结合,正是这一趋势的重要体现。 AI技术在SEO中的重要性 在数字营销领域,AI技术的引入为SEO策略带来了前所未有的变革。…...
保姆级教程Docker部署Kafka官方镜像
目录 一、安装Docker及可视化工具 二、单节点部署 1、创建挂载目录 2、运行Kafka容器 3、Compose运行Kafka容器 4、查看Kafka运行状态 三、集群部署 在Kafka2.8版本之前,Kafka是强依赖于Zookeeper中间件的,这本身就很不合理,中间件依赖…...
解析PHP文件路径相关常量
PHP文件路径相关常量包括以下几个常量: __FILE__:表示当前文件的绝对路径,包括文件名。 __DIR__:表示当前文件所在的目录的绝对路径,不包括文件名。 dirname(__FILE__):等同于__DIR__,表示当前…...
WPS计算机二级•幻灯片的配色、美化与动画
听说这是目录哦 配色基础颜色语言❤️使用配色方案🩷更改PPT的颜色🧡PPT动画添加的原则💛PPT绘图工具💚自定义设置动画💙使用动画刷复制动画效果🩵制作文字打字机效果💜能量站😚 配色…...
C#,shell32 + 调用控制面板项(.Cpl)实现“新建快捷方式对话框”(全网首发)
Made By 于子轩,2025.2.2 不管是使用System.IO命名空间下的File类来创建快捷方式文件,或是使用Windows Script Host对象创建快捷方式,亦或是使用Shell32对象创建快捷方式,都对用户很不友好,今天小编为大家带来一种全新…...
单纯信息展示的站点是否可以用UML建模
凌钦亮 More options Aug 7 2010, 10:36 am 现在社会上大量的网站需求都还只是用于单纯的企业信息展示,那此种网站是否有必要用UML 建模呢?业务用例图的一个个用例是用来卖的,但是他只有信息展示这个需 求,我是否在划分业务用例…...
FinRobot:一个使用大型语言模型的金融应用开源AI代理平台
“FinRobot: An Open-Source AI Agent Platform for Financial Applications using Large Language Models” 论文地址:https://arxiv.org/pdf/2405.14767 Github地址:https://github.com/AI4Finance-Foundation/FinRobot 摘要 在金融领域与AI社区间&a…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.19 线性代数核武器:BLAS/LAPACK深度集成
2.19 线性代数核武器: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 的延伸扩展。 问:运行 ls /usr/lib/fonts/ 发现有一个名叫 msyh.ttc 的字体文件,能介绍…...
Love Tester:探索爱情的深度与维度
爱情是什么?是相互帮助、耐心、理解、鼓励、保护、可靠和牺牲。Love Tester 通过先进的算法,分析名字的兼容性和关系的潜力,帮助你计算爱情匹配的准确性。 相互帮助:在伴侣遇到困难时伸出援手,这是爱情的体现。耐心&a…...
BFS(广度优先搜索)——搜索算法
BFS,也就是广度(宽度)优先搜索,二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS(深度优先搜索)。从字面意思也很好理解,DFS就是一条路走到黑,BFS则是一层一层地展开。…...
JVM 四虚拟机栈
虚拟机栈出现的背景 由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多…...
【R语言】获取数据
R语言自带2种数据存储格式:*.RData和*.rds。 这两者的区别是:前者既可以存储数据,也可以存储当前工作空间中的所有变量,属于非标准化存储;后者仅用于存储单个R对象,且存储时可以创建标准化档案,…...
Java BIO详解
一、简介 1.1 BIO概述 BIO(Blocking I/O),即同步阻塞IO(传统IO)。 BIO 全称是 Blocking IO,同步阻塞式IO,是JDK1.4之前的传统IO模型,就是传统的 java.io 包下面的代码实现。 服务…...
统计满足条件的4位数(信息学奥赛一本通-1077)
【题目描述】 给定若干个四位数,求出其中满足以下条件的数的个数:个位数上的数字减去千位数上的数字,再减去百位数上的数字,再减去十位数上的数字的结果大于零。 【输入】 输入为两行,第一行为四位数的个数n࿰…...
北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评
在IT行业中,地理信息系统(GIS)是用于处理、分析和展示地理空间数据的重要工具,而ArcGIS则是GIS领域中的一款知名软件。本文将详细解析标题和描述中提及的知识点,并结合“门头沟区建筑物数据”这一标签,深入…...
Spring 面试题【每日20道】【其三】
1、Spring 中的 Profile 注解的作用是什么? 中等 Profile 注解在Spring框架中用于根据不同的环境配置文件(profiles)来激活或忽略某些Bean的注册。它允许开发者定义逻辑以区分不同环境下的bean定义,例如开发、测试和生产环境。 …...
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数据湖技术成功地解决了其大规模数据处理和分析的难题,提高了数据处理效率和准确性,为公司的业务发展提供了有力的支持。 Apache Hudi数据湖技术的一个典型应用案例是网络打车系统的数据处理场景,具体如下: 大…...
5分钟掌握飞书文档高效转换:开源浏览器扩展的完整解决方案
5分钟掌握飞书文档高效转换:开源浏览器扩展的完整解决方案 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 还在为飞书文档格式转换而头疼吗?复…...
3分钟掌握微信聊天记录永久保存:从数据备份到智能分析完全攻略
3分钟掌握微信聊天记录永久保存:从数据备份到智能分析完全攻略 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...
告别手动复制粘贴!用Python-pptx库5分钟搞定PPT批量生成(附完整代码)
职场效率革命:Python-pptx全自动PPT生成实战指南 每次月度汇报前夜,市场部的张伟总要面对几十页PPT的复制粘贴地狱——从Excel拉数据、调整格式、核对图表,最后发现领导临时改了需求又得重来。这种场景在数据驱动型岗位中已成常态,…...
基于SpringBoot+Vue的网上商城系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】
💡实话实说:有自己的项目库存,不需要找别人拿货再加价,所以能给到超低价格。摘要 随着互联网技术的快速发展,电子商务已成为现代商业活动的重要组成部分。网上商城系统作为电子商务的核心载体,为用户提供了…...
机箱机柜模块化设计方法
在机箱机柜制造领域,模块化设计正逐渐成为提升生产效率、降低成本、增强产品灵活性的关键方法。今天,我们就来深入探讨机箱机柜模块化设计方法,同时为大家推荐深圳市机汇五金制品有限公司(以下简称“机汇五金”)&#…...
3分钟解锁百度网盘极速下载:BaiduPCS-Web高效解决方案全攻略
3分钟解锁百度网盘极速下载:BaiduPCS-Web高效解决方案全攻略 【免费下载链接】baidupcs-web 项目地址: https://gitcode.com/gh_mirrors/ba/baidupcs-web 还在为百度网盘的龟速下载而烦恼吗?今天我要为你介绍一个能够彻底改变下载体验的神器——…...
RAG视觉锚定:让大模型精准定位PDF中的图与表
1. 项目概述:让大模型真正“看见”文档里的图与表 “Visual Grounding for Advanced RAG Frameworks”——这个标题乍看像学术论文的副标题,但在我过去三年落地二十多个企业级RAG项目的过程中,它直指当前最棘手、也最容易被忽视的痛点&#x…...
车规级国际物联卡是什么?车载物联网硬件选型与行业标准解析
随着跨境整车出口、改装车辆、工程机械外销、车载定位终端普及,车载联网通信要求持续升级。普通民用SIM卡无法适配车辆颠簸、温差跨度大、高速移动、跨境切换网络的复杂工况,车规级国际物联卡逐步成为车载智能化硬件的标配通信载体。很多出海设备厂商容易…...
从原理到实践:InSAR技术如何重塑地表形变监测
1. 从雷达信号到毫米级形变:InSAR技术原理揭秘 想象一下,你站在湖边向平静的水面扔一块石头,水波会以同心圆的形式向外扩散。如果这时有人在水面另一处也扔了一块石头,两列水波相遇时就会产生干涉现象——有的地方波峰叠加变得更高…...
安全工程师的‘副驾驶’:手把手配置Xray+YAML,打造你的专属Web扫描策略
安全工程师的‘副驾驶’:手把手配置XrayYAML,打造你的专属Web扫描策略 在渗透测试和红队行动中,Web扫描器就像安全工程师的"副驾驶",而Xray无疑是当前最受青睐的选择之一。但很多工程师在使用过程中都会遇到这样的困扰&…...
