当前位置: 首页 > 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。

运行结果如下图所示:

以上就是本文的全部内容

http://www.lryc.cn/news/531508.html

相关文章:

  • AI与SEO关键词的完美结合如何提升网站流量与排名策略
  • 保姆级教程Docker部署Kafka官方镜像
  • 解析PHP文件路径相关常量
  • WPS计算机二级•幻灯片的配色、美化与动画
  • C#,shell32 + 调用控制面板项(.Cpl)实现“新建快捷方式对话框”(全网首发)
  • 单纯信息展示的站点是否可以用UML建模
  • FinRobot:一个使用大型语言模型的金融应用开源AI代理平台
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.19 线性代数核武器:BLAS/LAPACK深度集成
  • 开发板目录 /usr/lib/fonts/ 中的字体文件 msyh.ttc 的介绍【微软雅黑(Microsoft YaHei)】
  • Love Tester:探索爱情的深度与维度
  • BFS(广度优先搜索)——搜索算法
  • JVM 四虚拟机栈
  • 【R语言】获取数据
  • Java BIO详解
  • 统计满足条件的4位数(信息学奥赛一本通-1077)
  • 北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评
  • Spring 面试题【每日20道】【其三】
  • FFmpeg(7.1版本)在Ubuntu18.04上的编译
  • Apache Hudi数据湖技术应用在网络打车系统中的系统架构设计、软硬件配置、软件技术栈、具体实现流程和关键代码
  • 安全策略配置
  • c++ stl 遍历算法和查找算法
  • 【Envi遥感图像处理】008:波段(批量)分离与波段合成
  • 线程创建与管理 - 创建线程、线程同步(C++)
  • 【C语言篇】“三子棋”
  • 安培定律应用于 BH 曲线上的工作点
  • 深度求索DeepSeek横空出世
  • 【CSS】什么是响应式设计?响应式设计的基本原理,怎么做
  • 后盾人JS--继承
  • 提升开发效率:IDE使用技巧与插件推荐
  • 开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B与vllm实现推理加速的正确姿势(一)