【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;
}

运行演示

总结

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

相关推荐
HIT_Weston12 分钟前
18、【Ubuntu】【远程开发】技术方案分析:私网ip掩码
linux·tcp/ip·ubuntu
cccccc语言我来了16 分钟前
(Linux (6):从包管理到工具探索,构建系统操作基础认知)
linux·运维·服务器
8K超高清39 分钟前
高校巡展:中国传媒大学+河北传媒学院
大数据·运维·网络·人工智能·传媒
ben9518chen1 小时前
嵌入式Linux C语言程序设计九
linux·c语言
wuk9981 小时前
CentOS7环境搭建L2TP服务器
运维·服务器
恒创科技HK1 小时前
香港1核2G云服务器当网站服务器够用不?
运维·服务器
IT 小阿姨(数据库)2 小时前
PostgreSQL 之上的开源时序数据库 TimescaleDB 详解
运维·数据库·sql·postgresql·开源·centos·时序数据库
颜大哦2 小时前
linux安装mysql
linux·运维·mysql·adb
学习3人组2 小时前
Node.js 网站服务器开发
运维·服务器·node.js
来知晓2 小时前
Linux:WSL内存空间管理之清完内存C盘可用空间不增问题解决
linux·运维·服务器