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

news/2025/2/7 22:23:47/

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.ppmy.cn/news/1570165.html

相关文章

GD32F4xx系列微控制器中,定时器可以配置为霍尔传感器模式,用于处理霍尔传感器的输出信号

在GD32F4xx系列微控制器中&#xff0c;定时器可以配置为霍尔传感器模式&#xff0c;用于处理霍尔传感器的输出信号。 霍尔传感器通常用于检测磁场变化&#xff0c;广泛应用于电机控制、位置检测等场景。通过定时器的霍尔传感器模式&#xff0c;可以实现对霍尔传感器信号的捕获…

ONLYOFFICE 文档 8.3 已发布:PDF 图章、合并形状、更多格式支持等

ONLYOFFICE 最新版本的在线编辑器已发布&#xff0c;包含约 30 项新功能和多个错误修复。阅读本文&#xff0c;了解所有更新内容。 关于 ONLYOFFICE 文档 ONLYOFFICE 是一个开源项目&#xff0c;专注于高级和安全的文档处理。坐拥全球超过 1500 万用户&#xff0c;ONLYOFFICE …

数据实时推送至前端的主流方法总结

数据实时推送至前端的主流方法总结 引言方案WebSocket&#xff08;全双工双向通信&#xff09;Server-Sent Events (SSE)&#xff08;单向服务器推送&#xff09;长轮询&#xff08;Long Polling&#xff09;第三方库/服务响应式编程&#xff08;如 Spring WebFlux&#xff09;…

吴恩达深度学习——卷积神经网络实例分析

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 LeNet-5AlexNetVGG-16ResNets残差块 1*1卷积 LeNet-5 输入层&#xff1a;输入为一张尺寸是 32 32 1 32321 32321的图像&#xff0c;其中 32 32 3232 3232是图像的长和宽&…

Java 中的 Spring 框架,以及 Spring Boot 和 Spring Cloud 的区别?

Spring框架是一个开源的Java平台&#xff0c;主要用于简化企业级应用程序的开发。 它通过提供一系列的功能模块&#xff0c;帮助开发者解决常见的编程难题&#xff0c;从而提高开发效率和代码质量。 Spring框架的核心思想是“控制反转”&#xff08;IoC&#xff09;和“面向切…

vscode中的编辑器、终端、输出、调试控制台(转载)

在vscode中,编辑器、终端、输出和调试控制台是不同的功能区域,各自具有不同的功能和用途: 1.编辑器(Editor):编辑器是用于编写和编辑代码的主要区域。你可以在编辑器中打开、创建和保存代码文件,并进行代码的编写、 修改和格式化等操作。VSCode提供了丰富的功能来提高开发效率,…

inquirer介绍及配合lerna在Vue中使用示例

目录 安装基本用法使用多个提示框动态选择&#xff08;动态选项&#xff09;表单式输入配合lerna在Vue中使用示例 Inquirer 是一个用于创建交互式命令行工具的 Node.js 库&#xff0c;常用于收集用户输入。它提供了多种类型的提示框&#xff0c;可以用于创建交互式应用程序&…

无人机的续航能力和飞行效率概述!

一、续航能力对飞行效率的影响 续航时间限制任务范围&#xff1a; 无人机的续航能力直接决定了其能够持续执行任务的时间。续航时间短意味着无人机需要在更短的时间内完成任务或频繁更换电池&#xff0c;从而限制了任务的范围和复杂性。 续航影响作业效率&#xff1a; 长时…