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

    在这里插入图片描述

  • 相关阅读:
    Norms and Inner Products
    NLP标注工具Brat的简单使用
    JAVA物资物流管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
    简单的一个两层的一维卷积网络
    Jmeter 使用详解、性能压测分析与性能优化思路
    AMSR/ADEOS-II L1A Raw Observation Counts V003地球表面和大气微波辐射的详细观测数据
    MySQL的索引问题
    第三章:栈/队列 重点题
    彻底删除vscode以及vscode的插件记录
    Quartz手动修改数据库cron表达式(无须重启服务器即可更改定时时间)
  • 原文地址:https://blog.csdn.net/weixin_60915103/article/details/139253875