C++多线程学习08 使用list和互斥锁进行线程通信

一、抽象的线程类

先定义一个抽象的线程类:
该线程类实现了启动线程,停止线程,退出线程,查看线程是否退出的功能:
并将线程入口设为纯虚函数,让具体的线程类自己去实现

#include <thread>
class XThread
{
    
    
public:
    //启动线程
    virtual void Start();

    //设置线程退出标志 并等待
    virtual void Stop();

    //等待线程退出(阻塞)
    virtual void Wait();

    //线程是否退出
    bool is_exit();
private:
    //线程入口
    virtual void Main() = 0;
    bool is_exit_ = false;
    std::thread th_;
};

线程类的实现:
start():当调用Xthread类对象的start()时,先将退出标志置false,再将线程入口函数与this指针做为参数调用线程的构造函数
成员函数与普通函数的区别在于成员函数的第一个隐含的指针形参是this指针,通过该指针去访问类对象中的成员。
线程的构造函数只使用类中的函数指针是不够的,还需要对象的this指针
wait():如果当前线程是可加入的(不能是detach的),等待该线程退出
具体:线程的状态----joinable和detached
stop():将退出标志位置为true,具体的线程类的线程入口会在while循环中通过该标志位来判断是否继续循环,然后调用wait等待当前线程退出

#include "xthread.h"
using namespace std;
//启动线程
void XThread::Start()
{
    
    
    is_exit_ = false;
    th_ = thread(&XThread::Main, this);
}

//设置线程退出标志 并等待
void XThread::Stop()
{
    
    
    is_exit_ = true;
    Wait();
}

//等待线程退出(阻塞)
void XThread::Wait()
{
    
    
    if (th_.joinable())
        th_.join();
}

//线程是否退出
bool XThread::is_exit()
{
    
    
    return is_exit_;
}

二、具体线程类

继承自抽象线程类,又定义了一个sendmsg函数,其他线程通过调用该函数来给该具体线程类传递消息(线程通信)
main函数使用了override关键字,表示该函数是个重写,为了防止写错

class XMsgServer:public XThread
{
    
    
public:
    //给当前线程发消息
    void SendMsg(std::string msg);

private:
    //处理消息的线程入口函数
    void Main() override;

    //消息队列缓冲
    std::list<std::string> msgs_;

    //互斥访问消息队列
    std::mutex mux_;
    
};

该线程的入口函数功能为从消息队列中读取主线程发来的消息并显示出来
注意点如下:
01无限循环中要加入sleep,不然可能入口函数可能一直占着CPU,(两个while循环中间隔很短,在这个间隔中CPU不一定能调度去执行其他线程,在这里的表现就是一直运行接收消息队列,发送消息队列一直获取不到锁,消息队列都空了还在接收,这样当然是不行的)
02利用unique_lock来管理互斥资源,不用去专门解锁

#include "xmsg_server.h"
#include <iostream>
using namespace std;
using namespace this_thread;
//处理消息的线程入口函数
void XMsgServer::Main()
{
    
    
    while (!is_exit())
    {
    
    
        sleep_for(10ms);
        unique_lock<mutex> lock(mux_);
        if (msgs_.empty())
            continue;
        while (!msgs_.empty())
        {
    
    
            //消息处理业务逻辑
            cout << "recv : " << msgs_.front() << endl;
            msgs_.pop_front();
        }

    }
}

//给当前线程发消息
void XMsgServer::SendMsg(std::string msg)
{
    
    
    unique_lock<mutex> lock(mux_);
    msgs_.push_back(msg);
}

三、主函数

#include "xmsg_server.h"
#include <sstream>
using namespace std;
int main(int argc, char* argv[])
{
    
    
    XMsgServer server;
    server.Start();
    for (int i = 0; i < 10; i++)
    {
    
    
        stringstream ss;
        ss << " msg : " << i + 1;
        server.SendMsg(ss.str());
        this_thread::sleep_for(500ms);
    }
    server.Stop();
    return 0;
}

主函数产生10个msg发给处理消息的子线程
,效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42567607/article/details/126058067
今日推荐