【Linux】23. 线程封装

发布于:2024-06-01 ⋅ 阅读:(92) ⋅ 点赞:(0)

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

#include <iostream>
#include <unistd.h>
#include <thread>

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 <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include <cassert>

// 先声明 要使用
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<void*(void*)>; -- 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 <memory>
#include <unistd.h>

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

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到