• 【Linux】23. 线程封装


    如何理解C++11中的多线程(了解)

    #include 
    #include 
    #include 
    
    void thread_run()
    {
        while (true)
        {
            std::cout << "我是新线程..." << std::endl;
            sleep(1);
        }
    }
    int main()
    {
        // 任何语言需要在Linux上实现多线程,必定是要用到pthread库的!
        // 如何看待C++11中的多线程呢?
        // 本质上就是对pthread库的封装
        std::thread t1(thread_run);
    
        while (true)
        {
            std::cout << "我是主线程..." << std::endl;
            sleep(1);
        }
    
        t1.join();
    
        return 0;
    }
    

    在这里插入图片描述

    封装代码

    封装代码写在Thread.hpp 文件当中,未来想使用封装好的线程就直接包含Thread.hpp文件即可!

    // hpp 表示header only 开源代码
    // 将函数定义和声明放在一起
    
    #pragma once
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // 先声明 要使用
    class Thread;
    
    // 上下文,当大号结构体使用
    // 用Context来处理静态方法调用不了成员变量的问题
    class Context
    {
    public:
        Thread *this_;
        void *args_;
    
    public:
        Context() : this_(nullptr), args_(nullptr)
        {}
        ~Context()
        {}
    };
    
    // 对线程做封装,以后就不需要总去调用原生库的接口了
    class Thread
    {
    public:
        // using func_t = std::function; -- C++11 智能指针
        typedef std::function<void *(void *)> func_t;
        const int num = 1024;
    
        // "void *(Thread::*)(void *args)" 类型的实参与 "void *(*)(void *)" 类型的形参不兼容C/C++(167) -- 报错
        // 为啥呢? -- 因为start_routine是类内的成员函数,有缺省参数this指针
        // void* start_routine(void* args)
        // {
        //     return func_(args);
        // }
    
        // 在类内创建线程  这样就没有this指针了
        static void *start_routine(void *args)
        {
            // 但是没有this指针
            // 静态方法不能调用成员方法或成员变量
            // return func_(args);
            // 可以采用友元,或者public成员的方式 这里不用!!
            
            // 将args强转成Context的指针
            Context *ctx = static_cast<Context*>(args);
            // 调用run方法 -- 将方法从静态中剥离出来
            void* ret = ctx->this_->run(ctx->args_);
            delete ctx;
            return ret;
        }
    
        // 构造函数
        Thread(func_t func, void *args = nullptr, int number = 0) : func_(func), args_(args)
        {
            char buffer[num];
            snprintf(buffer, sizeof buffer, "thread-%d", number);
            name_ = buffer;
    
            // 加上Context
            Context* ctx = new Context();
            ctx->this_ = this;
            ctx->args_ = args_;
            // 将ctx传过去
            int n = pthread_create(&tid_, nullptr, start_routine, ctx);
            //int n = pthread_create(&tid_, nullptr, start_routine, args);
            assert(n == 0);
            (void)n;
        }
    
        // 线程等待
        void join()
        {
            int n = pthread_join(tid_, nullptr);
            assert(n == 0);
            (void)n;
        }
    
        void *run(void *args)
        {
            return func_(args);
        }
    
        // 析构
        ~Thread()
        {
            // do nothing
        }
    
    private:
        // 自定义线程名 方便观察(不需要通过观察tid)
        // 末尾加_ 将成员变量和参数做区分
        std::string name_;
        pthread_t tid_;
        // 线程执行任务
        func_t func_;
        // 获取参数
        void *args_;
    };
    
    

    使用封装

    #include "Thread.hpp"
    #include 
    #include 
    
    void *thread_run(void *args)
    {
        std::string work_type = static_cast<const char *>(args);
        while (true)
        {
            std::cout << "我是一个新线程,我正在做:" << work_type << std::endl;
            sleep(1);
        }
    }
    
    int main()
    {
        std::unique_ptr<Thread> thread1(new Thread(thread_run, (void *)"hellothread", 1));
        std::unique_ptr<Thread> thread2(new Thread(thread_run, (void *)"countthread", 2));
        std::unique_ptr<Thread> thread3(new Thread(thread_run, (void *)"printthread", 3));
        std::unique_ptr<Thread> thread4(new Thread(thread_run, (void *)"iothread", 4));
    
        thread1->join();
        thread2->join();
        thread3->join();
        thread4->join();
        return 0;
    }
    

    在这里插入图片描述

  • 相关阅读:
    nginx配置域名不需要项目名称
    深入了解直播美颜工具与视频美颜SDK的实现与优化策略
    Anaconda3 spyder无法打开问题解决实录
    JS代码案例
    Django项目配置
    【Android】-- Activity页面(启动和结束、生命周期、启动模式和实例)
    DBCO-SS-Mal,DBCO-SS-Maleimide,马来酰亚胺衍生物试剂特点分析
    Java 21 新特性:Unnamed Classes and Instance Main Methods
    搞懂 MySql 的架构和执行流程
    CodeTON Round 3 (Div. 1 + Div. 2, Rated, Prizes!) A~D 题解
  • 原文地址:https://blog.csdn.net/weixin_60915103/article/details/139253875