【Linux跬步积累】——thread封装

🌏博客主页:PH_modest的博客主页

🚩当前专栏:Linux跬步积累

💌其他专栏:

🔴 每日一题

🟡 C++跬步积累

🟢 C语言跬步积累

🌈座右铭:广积粮,缓称王!

文章目录


创建文件

首先创建一个.hpp文件和一个.cc文件,.hpp文件内进行对thread的封装,然后在.cc文件下进行测试。

提示:.hpp文件是类似于.h文件,更多用于C++中,用于和C语言的进行区分,.hpp文件内包含类、模版、函数、宏的定义和声明,它允许在多个源文件中共享代码,避免重复编写。

.hpp文件的创建、thread类的函数定义

cpp 复制代码
#ifndef __THREAD_HPP__ //避免头文件重复包含
#define __THREAD_HPP__

#include<iostream>
#include<string>
#include<pthread.h>
#include<functional>
#include<unistd.h>

//命名空间
namespace ThreadModule
{
    template<class T>
    using func_t = std::function<void(T&)>;//模版方法,下面参数的定义也要带模版

    template<class T>
    class Thread
    {
    public:
        Thread(func_t<T> func,const T &data,const std::string &name="none_name")
            :_func(func),_data(data),_threadname(name),_stop(true)
        {}
        bool Start()//启动并创建线程
        {}
        void Detach()//分离线程
        {}
        void Join()//等待线程
        {}
        void Stop()//终止线程
        {}
        ~Thread()
        {}
    private:
        pthread_t _tid;
        std::string _threadname;
        T _data;
        func_t<T> _func;
        bool _stop;
    };

}//namespace ThreadModule
#endif

.cc文件的创建

cpp 复制代码
#include "Thread.hpp"
#include <iostream>
#include<vector>

using namespace ThreadModule;

const int num=10;

int main()
{
    //1.创建一批线程
    
    //2.启动一批线程
    
    //3.等待一批线程
    
    return 0;
}

.hpp内thread类基础函数的实现

cpp 复制代码
#ifndef __THREAD_HPP__
#define __THREAD_HPP__

#include<iostream>
#include<string>
#include<pthread.h>
#include<functional>
#include<unistd.h>

//命名空间
namespace ThreadModule
{
    template<class T>
    using func_t = std::function<void(T&)>;//模版方法,下面参数的定义也要带模版

    template<class T>
    class Thread
    {
    public:
        void Excute()
        {
            _func(_data);
        }
    public:
        Thread(func_t<T> func,const T &data,const std::string &name="none_name")
            :_func(func),_data(data),_threadname(name),_stop(true)
        {}

        static void* Threadroutinue(void* args)//类成员函数,形参是有this指针的!!!,不满足pthread_create的传参要求。所以需要加static
        {
            Thread<T>* self=static_cast<Thread<T>*>(args);
            self->Excute();
            return nullptr;
            
            //会报错,因为访问成员函数前需要加this指针,但是static没有this指针
            //_func(_data);

            //测试代码
            // while(true)
            // {
            //     std::cout<<"I am new thread..."<<std::endl;
            //     sleep(1);
            // }
        }
        
        bool Start()
        {
            int n = pthread_create(&_tid,nullptr,Threadroutinue,this);
            if(!n)
            {
                _stop=false;
                return true;
            }
            else
            {
                return false;
            }
        }
        void Detach()
        {
            if(!_stop)
                pthread_detach(_tid);
        }
        void Join()
        {
            if(!_stop)
                pthread_join(_tid,nullptr);
        }
        void Stop()
        {
            _stop=true;
        }
        std::string name()
        {
            return _threadname;
        }
        ~Thread()
        {}
    private:
        pthread_t _tid;
        std::string _threadname;
        T _data;
        func_t<T> _func;
        bool _stop;
    };

}//namespace ThreadModule

#endif

知识点1:

其他函数的实现只需要调用pthread库就可以了,但是我们使用pthread_create()函数来调用成员函数Threadroutinue()时,如果Threadroutinue()前面不加static则会报错,因为pthread_create()第三个参数是一个返回值为void*,参数为void*的一个函数,而成员函数会隐藏一个this指针,这就会导致出错,因此我们只需要加上static,那么成员函数就不会带有this指针了。

但是当我们想用成员函数Threadroutinue()调用成员变量_func,来使用外部传递的函数时,因为没有this指针,导致我们无法调用,这又应该如何解决呢?

于是我们可以再定义一个函数Excute(),我们使用Excute()来调用_func,然后pthread_create()函数的第四个参数传递this指针,这样Threadroutinue()就可以用传递的this指针调用Excute()函数了,这样就可以完美解决问题。

知识点2:

我们可以使用#include<functional>头文件内的function函数来定义一个函数指针,类似于文中的std::function<void(T&)>,这里的void表示函数的返回值,T&表示函数的参数 。因此我们之后就可以传递void Printf(int &data)函数给线程了。

.cc内thread类的简单调用

cpp 复制代码
#include "Thread.hpp"
#include <iostream>
#include<vector>

using namespace ThreadModule;

void Printf(int &data)
{
    while(data)
    {
        std::cout<<"hello I am myself thread,data:"<<data--<<std::endl;
        sleep(1);
    }
}


const int num=10;

int main()
{
    std::vector<Thread<int>> threads;
    //1.创建一批线程
    for(int i=0;i<num;i++)
    {
        std::string name = "thread-"+std::to_string(i+1);
        threads.emplace_back(Printf,10,name);
    }
    //2.启动一批线程
    for(auto &thread:threads)
    {
        thread.Start();
    }
    //3.等待一批线程
    for(auto &thread:threads)
    {
        thread.Join();
        std::cout<<"wait thread done...thread is"<<thread.name()<<std::endl;
    }
    return 0;
}

运行演示

总结

本篇博客没有过多讲解代码,这里是默认大家都能看懂的,主要是为了讲解一下文中的两个知识点,如果对代码部分有疑问可以看看我的前几篇有关线程的博客。

相关推荐
不知 不知19 分钟前
最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
linux·运维·服务器·centos
BUG 40427 分钟前
Linux--运维
linux·运维·服务器
千航@abc33 分钟前
vim在末行模式下的删除功能
linux·编辑器·vim
MXsoft6181 小时前
华为E9000刀箱服务器监控指标解读
大数据·运维
贾贾20231 小时前
配电网的自动化和智能化水平介绍
运维·笔记·科技·自动化·能源·制造·智能硬件
九月十九2 小时前
AviatorScript用法
java·服务器·前端
发光小北2 小时前
关于六通道串口服务器详细讲解
运维·硬件工程
jcrose25802 小时前
Ubuntu二进制部署K8S 1.29.2
linux·ubuntu·kubernetes
爱辉弟啦2 小时前
Windows FileZila Server共享电脑文件夹 映射21端口外网连接
linux·windows·mac·共享电脑文件夹
ICT系统集成阿祥2 小时前
科普篇 | “机架、塔式、刀片”三类服务器对比
运维·服务器