【Linux】:封装线程

朋友们、伙计们,我们又见面了,本期来给大家带来封装线程相关的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

​ 

目录

引言:

1. 基础框架 

1.1 初步Start接口

1.2 修正后的Start接口

2. Join接口

 2.1 初步测试

3. 添加模版

4. 全部代码


引言:

我们想要通过封装原生线程库的方式来实现一个类似于C++11里面的线程库,这里只是为了来更沉入的学习原生线程库,实现一些基础的功能即可;

我们创建一个mian.cc文件用于测试线程逻辑;

Thread.hpp主要用于封装线程;

Makefile主要实现自动化代码构建。

1. 基础框架 

  • 我们想要封装的线程需要有对应的线程id、线程名、该线程是否运行以及线程所要执行的任务;
  • 线程所需要执行的任务我们需要用函数包装器(functional)
  • 我们想要实现的方法有一个让线程启动起来的方法,还需要有一个等待线程的方法;
  • 后面根据需要添加对应的成员和方法。

Thread.hpp:

先将基础框架搭建出来,后面再慢慢补充所需要的接口以及代码。

1.1 初步Start接口

在Start接口就是用来启动线程,那么在接口设计中就需要先创建进程,在对应的线程执行方法中执行我们预先设计好的func;

这里就需要注意一下线程封装时的细节,我们先来看一下创建线程的接口具体传递的参数:

我们设置的线程执行方法函数的参数只有一个参数,但是因为我们自己设置的ThreadRoutine函数是类内函数,那么类内函数会默认自己带一个this指针,所以这于原始函数设计接口不符,所以我们需要将该函数设置为静态成员函数,然后我们将this指针传递给他,然后通过this指针来调用我们预设的func;

1.2 修正后的Start接口

2. Join接口

在实现Join之前我们可以设置一个查看线程是否运行的接口以及获取线程名的接口,方便后面的测试;

在等待线程这里我们直接使用原生线程库的接口:

我们目前不关心等待的结果;

 2.1 初步测试

上面的代码算是一份非常简单的线程封装代码,那么接下来我们使用main.cc来使用一下我们封装的线程库,因为我们将线程对象化了,所以我们就可以用容器来保存我们的线程,这其实就是一种“先描述,再组织”的过程。

#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>#include "Thread.hpp"
// 设置线程名
std::string GetThreadName()
{static int num = 1;char buffer[64];snprintf(buffer, sizeof(buffer), "Thread-%d", num++);return buffer;
}void Print()
{while(1){std::cout << "hello thread" << std::endl;sleep(1);}
}int main()
{std::vector<Thread> threads;int num = 5;// 创建for(int i = 0; i< num; i++){threads.push_back(Thread(GetThreadName(),Print));}for (auto &t : threads){std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;}// 启动for (auto &t : threads){t.Start();}for (auto &t : threads){std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;}// Joinfor (auto &t : threads){t.Join();}return 0;
}

3. 添加模版

我们想给我们的线程传递参数,所以我们需要添加模版;

整体代码:

#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>template <class T>
using func_t = std::function<void(T)>; // 任务template <class T>
class Thread
{
public:Thread(const std::string &threadname, func_t<T> func, T data): _tid(0), _thread_name(threadname), _isrunning(false), _func(func), _data(data){}// 执行方法static void* ThreadRoutine(void *args){Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}// 启动bool Start(){int n = pthread_create(&_tid, nullptr, ThreadRoutine, this); // 将this指针传递给ThreadRoutineif(n == 0){_isrunning = true;return true;}else return false;}// 等待bool Join(){if (!_isrunning)return false;int n = pthread_join(_tid, nullptr);if (n == 0){return true;}return false;}bool IsRunning(){return _isrunning;}std::string ThreadName(){return _thread_name;}~Thread() {}private:pthread_t _tid;           // 线程idstd::string _thread_name; // 线程名bool _isrunning;          // 线程是否运行func_t<T> _func;             // 线程所执行任务T _data;                   // 传递数据类型
};

4. 全部代码

Makefile

thread:main.ccg++ -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:rm -f thread

main.cc

#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>#include "Thread.hpp"
// 设置线程名
std::string GetThreadName()
{static int num = 1;char buffer[64];snprintf(buffer, sizeof(buffer), "Thread-%d", num++);return buffer;
}void Print(int num)
{while(num--){std::cout << "hello thread num :" << num << std::endl;sleep(1);}
}int main()
{Thread<int> t(GetThreadName(), Print, 5);t.Start();t.Join();// std::vector<Thread> threads;// int num = 5;// // 创建// for(int i = 0; i< num; i++)// {//     threads.push_back(Thread(GetThreadName(),Print));// }// for (auto &t : threads)// {//     std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;// }// // 启动// for (auto &t : threads)// {//     t.Start();// }// for (auto &t : threads)// {//     std::cout << t.ThreadName() << ", is running: " << t.IsRunning() << std::endl;// }// // Join// for (auto &t : threads)// {//     t.Join();// }// Thread ts(Printf, GetThreadName());// std::cout << "is thread running? " << ts.IsRunning() << std::endl;// ts.Start();// std::cout << "is thread running? " << ts.IsRunning() << std::endl;// ts.Join();return 0;
}

Thread.hpp

#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>template <class T>
using func_t = std::function<void(T)>; // 任务template <class T>
class Thread
{
public:Thread(const std::string &threadname, func_t<T> func, T data): _tid(0), _thread_name(threadname), _isrunning(false), _func(func), _data(data){}// 执行方法static void* ThreadRoutine(void *args){Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}// 启动bool Start(){int n = pthread_create(&_tid, nullptr, ThreadRoutine, this); // 将this指针传递给ThreadRoutineif(n == 0){_isrunning = true;return true;}else return false;}// 等待bool Join(){if (!_isrunning)return false;int n = pthread_join(_tid, nullptr);if (n == 0){return true;}return false;}bool IsRunning(){return _isrunning;}std::string ThreadName(){return _thread_name;}~Thread() {}private:pthread_t _tid;           // 线程idstd::string _thread_name; // 线程名bool _isrunning;          // 线程是否运行func_t<T> _func;             // 线程所执行任务T _data;                   // 传递数据类型
};

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

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

相关文章

全球领先的光学方案设计公司:倚光科技

在光学技术革新的浪潮中&#xff0c;倚光&#xff08;深圳&#xff09;科技有限公司以创新者的姿态迅速崛起&#xff0c;成为全球光学领域的标杆企业。自 2021 年成立以来&#xff0c;公司始终聚焦纳米光学技术研发与超精密加工&#xff0c;凭借顶尖的技术实力和前瞻性的市场布…

2.2.3 TCP—UDP-QUIC

文章目录 2.2.3 TCP—UDP-QUIC1. TCP如何做到可靠性传输1. ACK机制2. 重传机制3. 序号机制4. 窗口机制5. 流量机制6. 带宽机制 2. tcp和udp如何选择1. tcp和udp格式对比2. ARQ协议&#xff08;Automatic Repeat reQuest&#xff0c;自动重传请求&#xff09;1. ARQ协议的主要类…

【动手实验】TCP 连接的建立与关闭抓包分析

本文是基于知识星球程序员踩坑案例分享中的作业进行的复现和总结&#xff0c;借此加深对 TCP 协议的理解&#xff0c; 原文参见TCP 连接的建立和关闭 —— 强烈建议新手看看。 实验环境 这里使用两台位于同一子网的腾讯云服务器&#xff0c;IP 分别是 node2&#xff08;172.1…

视频理解之Actionclip(论文宏观解读)

配合解读代码解读 1.研究背景 1. 视频行为识别的重要性 视频行为识别是视频理解领域的核心任务之一&#xff0c;旨在通过分析视频内容来识别和分类其中的人物行为或活动。这一任务在多个领域具有重要的应用价值&#xff0c;例如智能监控、人机交互、自动驾驶、医疗健康等。随…

基于LabVIEW的脚本化子VI动态生成

该示例展示了一种利用LabVIEW VI脚本&#xff08;VI Scripting&#xff09;技术&#xff0c;通过程序化方式动态生成并替换子VI的解决方案。核心逻辑为&#xff1a;基于预定义的模板VI&#xff0c;根据用户选择的数学操作&#xff08;加法或乘法&#xff09;&#xff0c;自动生…

Debian系统grub新增启动项

参考链接 给grub添加自定义启动项_linux grub定制 启动项名称自定义-CSDN博客 www.cnblogs.com 1. boot里面的grub.cfg 使用vim打开boot里面的grub.cfg sudo vim /boot/grub/grub.cfg 这时候会看到文件最上方的提示 2. 真正配置grub的文件 从刚才看到的文件提示中&#x…

ctfhub-web-SSRF通过攻略

1.URL Bypass 打开题目 请求的URL中必须包含http://notfound.ctfhub.com&#xff0c;使用来绕过即可 /?urlhttp://notfound.ctfhub.com127.0.0.1/flag.php 成功获得flag 2.数字IP Bypass 开启题目 发现127以及172被过滤了 尝试别的绕过 127.0.0.1–>localhost 127.0…

C语言(23)

字符串函数 11.strstr函数 1.1函数介绍&#xff1a; 头文件&#xff1a;string.h char *strstr ( const char * str1,const char *str2); 作用&#xff1a;在一个字符串&#xff08;str1&#xff09;中寻找另外一个字符串&#xff08;str2&#xff09;是否出现过 如果找到…

uniapp+Vue3 组件之间的传值方法

一、父子传值&#xff08;props / $emit 、ref / $refs&#xff09; 1、props / $emit 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 $emit 触发事件向父组件传递数据。 父组件&#xff1a; // 父组件中<template><view class"container">…

晨控CK-FR08与汇川H5U系列PLC配置EtherNet/IP通讯连接手册

晨控CK-FR08与汇川H5U系列PLC配置EtherNet/IP通讯连接手册 晨控CK-FR08系列作为晨控智能工业级别RFID读写器,支持大部分工业协议如RS232、RS485、以太网。支持工业协议Modbus RTU、Modbus TCP、Profinet、EtherNet/lP、EtherCat以及自由协议TCP/IP等。 本期主题&#xff1a;围…

BLDC直流无刷电机转速电流双闭环调速MATLAB仿真

微♥&#xff1a;“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2017Ra&#xff09;软件。建议采用matlab2017 Ra及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff09; 2.仿真算法&#x…

Windows 11下Git Bash执行cURL脚本400问题、CMD/PowerShell不能执行多行文本等问题记录及解决方案

问题 在Postman里可成功执行的POST请求&#xff1a; 找到Postman的Code 因为cURL基本上算是行业标准&#xff0c;所以Postman默认选中cURL&#xff0c;支持切换不同的开发语言&#xff1a; 点击上图右上角的复制按钮&#xff0c;得到cURL脚本。 Windows 11家庭版&#xff…

4个 Vue 路由实现的过程

大家好&#xff0c;我是大澈&#xff01;一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff0c;关注我&#xff0c;科技未来或许我能帮到你&#xff01; Vue 路由相信朋友们用的都很熟了&#xff0c;但是你知道 Vue 路由…

es-索引详解

在 Elasticsearch 中&#xff0c;**索引&#xff08;Index&#xff09;**是核心概念之一&#xff0c;类似于关系型数据库中的“表”。索引用于存储、组织和检索文档&#xff08;Document&#xff09;。以下是关于 Elasticsearch 索引的详细解析&#xff1a; 1. 索引的基本概念 …

C#实现本地Deepseek模型及其他模型的对话v1.4

前言 系 统&#xff1a;Window11 开发工具&#xff1a;Visual Studio 2022 相关技术&#xff1a;C# 、WPF .Net 8.0 1、C#实现本地AI聊天功能 WPFOllamaSharpe实现本地聊天功能,可以选择使用Deepseek 及其他模型。 新增根据聊天记录回复的功能。 优化了部分ViewModel&#xff…

若依框架-给sys_user表添加新字段并获取当前登录用户的该字段值

目录 添加字段 修改SysUser类 修改SysUserMapper.xml 修改user.js 前端获取字段值 添加字段 若依框架的sys_user表是没有age字段的&#xff0c;但由于业务需求&#xff0c;我需要新添加一个age字段&#xff1a; 修改SysUser类 添加age字段后&#xff0c;要在SysUser类 …

用Qt手搓AI助手,挑战24小时开发DeepSeek Assistant!

一、项目需求分析与技术选型 DeepSeekAssistant是一款基于深度求索&#xff08;DeepSeek&#xff09;API的智能对话助手&#xff0c;核心需求包括&#xff1a; 用户界面友好&#xff1a;支持多轮对话展示数据持久化&#xff1a;历史记录存储与检索异步网络通信&#xff1a;AP…

linux 软件扩展GPU显存

概述 共享内存可以通过 Unified Memory&#xff08;统一内存&#xff09;来实现&#xff0c;它允许 CPU 和 GPU 共享相同的内存地址空间&#xff0c;从而方便数据的传输和访问。 利用该技术可解决家用GPU 机器学习时显存不足的问题 &#xff08;注&#xff1a; 虽然解决了爆显…

Linux——进程初步

学进程前我们需要知道什么&#xff1f; 一、冯诺依曼体系结构 图中就是我们电脑运作时的大致工作流程&#xff0c;其中输入设备、输出设备我们也叫外设。其中&#xff0c;输入设备有比如键盘、鼠标、磁盘、摄像头等。输出设备有显示器、磁盘、打印机等。图中的存储器我们也叫内…

LeetCode-122. 买卖股票的最佳时机 II

其实这题画个折线图就很清晰了&#xff0c;因为我们每天都可以买卖股票&#xff0c;所有我们就只计算上升趋势的股票收益就好了&#xff0c;最小刻度为1&#xff0c;进行差值计算&#xff0c;取总和。 var maxProfit function(prices){let sum0;for(let i1;i<prices.leng…