【Linux】线程封装

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

一、为什么需要封装线程库?

pthread的痛点:

封装带来的好处:

二、线程封装核心代码解析

1. 头文件定义(Thread.hpp)

三、关键技术点详解

1. std::function的魅力

2. 静态成员函数的巧妙使用

3. 获取真实的线程ID

四、使用示例和测试代码

测试代码(main.cpp)


一、为什么需要封装线程库?

在Linux C++开发中,我们经常需要使用多线程。原生的pthread接口虽然强大,但存在一些问题:

pthread的痛点:

  • 🔧 C风格接口:函数指针和void*参数不够类型安全

  • 📝 冗长的代码:需要手动管理线程创建、连接、销毁

  • 🚫 易出错:容易忘记检查返回值,导致难以调试的问题

  • 🔄 缺乏RAII:资源管理需要手动处理

封装带来的好处:

  • 🎯 类型安全:使用std::function代替函数指针

  • 🚀 简洁易用:几行代码完成线程管理

  • 🛡️ 异常安全:利用RAII自动管理资源

  • 📦 可扩展性:方便添加新功能(如线程池)

二、线程封装核心代码解析

1. 头文件定义(Thread.hpp)

 

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <functional>
#include <sys/syscall.h>// 获取轻量级进程ID(线程ID)
#define get_lwp_id() syscall(SYS_gettid)// 定义函数类型别名
using func_t = std::function<void()>;class Thread
{
public:// 构造函数:接收线程函数和线程名Thread(func_t func, const std::string &name): _name(name), _func(func), _isrunning(false){}// 静态成员函数:线程启动例程static void *start_routine(void *args){Thread *self = static_cast<Thread *>(args);self->_isrunning = true;self->_lwpid = get_lwp_id();  // 获取实际线程IDself->_func();                // 执行用户函数pthread_exit((void *)0);      // 线程退出}// 启动线程void Start(){int n = pthread_create(&_tid, nullptr, start_routine, this);if (n == 0){std::cout << "线程" << _name << "创建成功" << std::endl;}}// 等待线程结束void Join(){if (!_isrunning) return;int n = pthread_join(_tid, nullptr);if (n == 0){std::cout << "线程" << _name << "回收成功" << std::endl;}}~Thread() {}private:bool _isrunning;        // 线程运行状态pthread_t _tid;         // 线程IDpid_t _lwpid;           // 轻量级进程IDstd::string _name;      // 线程名称func_t _func;           // 线程执行函数
};

三、关键技术点详解

1. std::function的魅力

传统pthread的问题:

 // C风格:需要静态函数和void*参数
void* thread_func(void* arg) {// 需要类型转换int* data = (int*)arg;// ...
}

我们的解决方案:

 

// C++11风格:类型安全的函数对象
using func_t = std::function<void()>;// 可以接收任何可调用对象:
// 1. 普通函数
// 2. Lambda表达式  
// 3. 函数对象
// 4. std::bind表达式

2. 静态成员函数的巧妙使用

为什么需要静态函数?
pthread_create要求C风格的函数指针,但普通成员函数有隐式的this参数。

解决方案:

 

static void *start_routine(void *args) {Thread *self = static_cast<Thread *>(args);  // 转换回对象指针self->_func();  // 调用真正的线程函数
}

3. 获取真实的线程ID

 

#define get_lwp_id() syscall(SYS_gettid)// 为什么需要这个?
// - pthread_t是进程内标识,在不同进程中可能重复
// - 通过系统调用获取的LWP ID是系统范围内唯一的
// - 便于调试和系统监控

四、使用示例和测试代码

测试代码(main.cpp)

 

#include "Thread.hpp"
#include <iostream>
#include <vector>// 测试函数
void Test()
{int cnt = 3;while (cnt--){std::cout << "线程" << get_lwp_id() << "正在运行..." << std::endl;sleep(1);}
}// Lambda表达式测试
auto lambda_test = []() {std::cout << "Lambda线程运行中" << std::endl;sleep(2);
};int main()
{std::cout << "=== 单线程测试 ===" << std::endl;Thread t1(Test, "single-thread");t1.Start();t1.Join();std::cout << "\n=== 多线程测试 ===" << std::endl;std::vector<Thread> threads;// 创建3个线程for (int i = 0; i < 3; i++){std::string name = "thread-";name += std::to_string(i + 1);threads.emplace_back(Test, name);}// 启动所有线程for (auto &thread : threads){thread.Start();}// 等待所有线程结束for (auto &thread : threads){thread.Join();}std::cout << "\n=== Lambda测试 ===" << std::endl;Thread t2(lambda_test, "lambda-thread");t2.Start();t2.Join();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97913.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97913.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧交通管理信号灯通信4G工业路由器应用

在交通信号灯管理中传统的有线通讯&#xff08;光纤、网线&#xff09;存在部署成本高、偏远区域覆盖难、故障维修慢等问题&#xff0c;而4G工业路由器凭借无线化、高稳定、强适配的特性&#xff0c;成为信号灯与管控平台间的数据传输核心&#xff0c;适配多场景需求。智慧交通…

《Python Flask 实战:构建一个可交互的 Web 应用,从用户输入到智能响应》

《Python Flask 实战:构建一个可交互的 Web 应用,从用户输入到智能响应》 一、引言:从“Hello, World!”到“你好,用户” 在 Web 应用的世界里,最打动人心的功能往往不是炫酷的界面,而是人与系统之间的真实互动。一个简单的输入框,一句个性化的回应,往往能让用户感受…

开发效率翻倍:资深DBA都在用的MySQL客户端利器

MySQL 连接工具&#xff08;也称为客户端或图形化界面工具&#xff0c;GUI Tools&#xff09;是数据库开发、管理和运维中不可或缺的利器。它们比命令行更直观&#xff0c;能极大提高工作效率。以下是一份主流的 MySQL 连接工具清单&#xff0c;并附上了它们的优缺点和适用场景…

基于Docker和Kubernetes的CI/CD流水线架构设计与优化实践

基于Docker和Kubernetes的CI/CD流水线架构设计与优化实践 本文分享了在生产环境中基于Docker和Kubernetes构建高效可靠的CI/CD流水线的实战经验&#xff0c;包括业务场景、技术选型、详细方案、踩坑与解决方案&#xff0c;以及最终的总结与最佳实践&#xff0c;帮助后端开发者快…

Trae x 图片素描MCP一键将普通图片转换为多风格素描效果

目录前言一、核心工具与优势解析二、操作步骤&#xff1a;从安装到生成素描效果第一步&#xff1a;获取MCP配置代码第二步&#xff1a;下载第三步&#xff1a;在 Trae 中导入 MCP 配置并建立连接第四步&#xff1a;核心功能调用三、三大素描风格差异化应用四.总结前言 在设计创…

2 XSS

XSS的原理 XSS&#xff08;跨站脚本攻击&#xff09;原理 1. 核心机制 XSS攻击的本质是恶意脚本在用户浏览器中执行。攻击者通过向网页注入恶意代码&#xff0c;当其他用户访问该页面时&#xff0c;浏览器会执行这些代码&#xff08;没有对用户的输入进行过滤导致用户输入的…

GitHub每日最火火火项目(9.3)

1. pedroslopez / whatsapp-web.js 项目名称&#xff1a;whatsapp-web.js项目介绍&#xff1a;基于 JavaScript 开发&#xff0c;是一个用于 Node.js 的 WhatsApp 客户端库&#xff0c;通过 WhatsApp Web 浏览器应用进行连接&#xff08;A WhatsApp client library for NodeJS …

Ansible变量

Ansible变量定义变量规则&#xff1a;由字母/数字/下划线组成&#xff0c;变量需要以字母开头&#xff0c;ansible内置的关键字不能作为变量。ansible中&#xff0c;可以将变量简化为三个范围&#xff1a;Global范围&#xff08;高&#xff09;&#xff1a;从命令行和ansible配…

Elasticsearch 核心特性与应用指南

最近在准备面试&#xff0c;正把平时积累的笔记、项目中遇到的问题与解决方案、对核心原理的理解&#xff0c;以及高频业务场景的应对策略系统梳理一遍&#xff0c;既能加深记忆&#xff0c;也能让知识体系更扎实&#xff0c;供大家参考&#xff0c;欢迎讨论。一、核心优势 Ela…

力扣115:不同的子序列

力扣115:不同的子序列题目思路代码题目 给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数。 测试用例保证结果在 32 位有符号整数范围内。 思路 首先我们来考虑特殊情况&#xff0c;当s串的长度小于t串时s串肯定就没有t串了。其他情况我们就需…

2004-2023年各省生活垃圾无害化处理率数据(无缺失)

2004-2023年各省生活垃圾无害化处理率数据&#xff08;无缺失&#xff09; 1、时间&#xff1a;2004-2023年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;生活垃圾无害化处理率 4、范围&#xff1a;30省 5、指标解释&#xff1a;生活垃圾无害化处理率指报…

【Python练习题】Python小白必练100题答案-第21-40题

练习题直达链接Python小白必练100题答案-第1-20题点我直达Python小白必练100题答案-第21-40题点我直达Python小白必练100题答案-第41-60题点我直达Python小白必练100题答案-第61-80题点我直达Python小白必练100题答案-第81-97题点我直达目录专栏导读循环结构 字符串操作第三部…

添加⽂件--场景⼆

添加⽂件–场景⼆ 学习到这⾥&#xff0c;我们已经清楚了如何向仓库中添加⽂件&#xff0c;并且对于⼯作区、暂存区、版本库也有了⼀定的认识。那么我们再展⽰⼀种添加⽂件的场景&#xff0c;能加深对⼯作区、暂存区、版本库的理解&#xff0c;⽰例如下&#xff1a; roothcss-e…

华为网路设备学习-31(BGP协议 六)

BGP路由属性的几种常见使用方法&#xff1a; 29章是 BGP路由汇总 与 as-path-filter&#xff08;正则表达式&#xff09; 30章是 Community 的使用方法 本章是 ip前缀列表ip-prefix 、 路由过滤 filter-policy 和路由策略 route-policy 一、在BGP中的 ip前缀列表&#xf…

Windows PostgreSQL JDBC驱动安装包位置

要在Windows系统上获取PostgreSQL JDBC驱动安装包&#xff08;后缀为.jar的文件&#xff09;&#xff0c;可通过以下官方及常用渠道获取&#xff0c;具体位置如下&#xff1a; ###&#x1f527; 1. 官方网站下载&#xff08;推荐&#xff09; 下载地址&#xff1a;https://jdb…

机器学习从入门到精通 - 聚类算法大比拼:K-Means、DBSCAN实战与评估陷阱

机器学习从入门到精通 - 聚类算法大比拼&#xff1a;K-Means、DBSCAN实战与评估陷阱 开场白&#xff1a;推开无监督学习的大门 朋友们&#xff0c;不知道你们有没有对着堆积如山、没有标签的数据发过愁&#xff1f;想从里面找出点规律&#xff0c;分组什么的&#xff0c;结果发…

AI 重构内容创作:从文案生成到视频剪辑,创作者该如何与 AI 协同共生?

一、引言&#xff1a;AI 掀起内容创作的 “重构浪潮”​行业现象引入&#xff1a;列举 AI 在内容创作领域的爆发式应用案例&#xff08;如某平台 AI 文案工具日生成量破百万、AI 视频剪辑软件用户增长超 300%&#xff09;​创作者需求变化&#xff1a;通过调研数据说明创作者对…

后端一次性返回十万条数据时,前端需要采用多种性能优化策略来避免页面卡顿

当后端一次性返回十万条数据时&#xff0c;前端需要采用多种性能优化策略来避免页面卡顿。以下是主要的优化方案&#xff1a; 分页加载 - 将数据分批次加载显示虚拟滚动 - 只渲染可视区域内的数据数据懒加载 - 按需加载数据Web Workers - 在后台线程处理数据时间切片 - 分散渲染…

基于-轻量级文档搜索系统的测试报告

文章目录一、项目背景二、项目功能三、测试计划&#xff08;一&#xff09;测试用例设计&#xff08;二&#xff09;测试用例实现1.功能测试2.界面测试3.兼容性测试4.易用性测试5.安全性测试一、项目背景 1.基于轻量级文档检索系统采用C技术栈来实现&#xff0c;同时使用了本地…

编辑器vim(Linux)

Linux下开发工具是独立的写代码——编辑器 vim编译代码——gcc/g调试——gdb、cgdb构建工具——makefile、make、cmakevim只用来写代码注意&#xff1a;直接用vim打开一个不存在的文件并保存退出&#xff0c;就会自动生成该文件vim有多种模式命令模式&#xff08;Normal Mode&a…