C++多线程编程(第三章 案例1,使用互斥锁+ list模拟线程通信)

主线程和子线程进行list通信,要用到互斥锁,避免同时操作

1、封装线程基类XThread控制线程启动和停止;

2、模拟消息服务器线程,接收字符串消息,并模拟处理;

3、通过Unique_lock和mutex互斥方位list 消息队列

4、主线程定时发送消息给子线程;

代码包含了XThread类(基类)、XMsgSever类(消息)、测试主程序

cpp 复制代码
//XThread.h 类(基类)
#pragma once
#include <thread>

//基类
class XThread
{
public:
	virtual void Start();//启动线程
	virtual void Stop();//设置线程退出标志,并等待
	virtual void Wait();//等待
	virtual bool is_exit();//线程是否退出

private:
	virtual void Main() = 0;//线程入口,纯虚函数,子函数必须单独实现
	bool is_exit_ = false;
	std::thread th_;

};
cpp 复制代码
//XThread.cpp 类(基类)
#include "XThread.h"

using namespace std;//在CPP中引用using namespace
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_;
}
cpp 复制代码
//XMsgSever.h 类
#pragma once
#include "XThread.h"
#include <list>
#include <mutex>
class XMsgSever:public XThread
{
public:
	//给当前线程发消息
	void SendMsg(std::string msg);



private:
	void Main()override;//重写main,override检查名字是否写错

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

	std::mutex mux_;//互斥访问消息队列
};
cpp 复制代码
//XMsgSever.cpp 类
#include "XMsgSever.h"
#include <iostream>

using namespace std;


void XMsgSever::SendMsg(std::string msg)
{//消息生产者
	unique_lock<mutex> lock(mux_);//为了保证list的线程安全,加锁
	msgs_.push_back(msg);
}

void XMsgSever::Main()
{//消息消费者
	while (!is_exit())
	{
		this_thread::sleep_for(10ms);
		unique_lock<mutex> lock(mux_);
		if (msgs_.empty())
		{//如果没有消息,则continue
			continue;
		}
		while (!msgs_.empty())
		{//消息处理业务逻辑
			cout << "recv: " << msgs_.front().c_str() << endl;
			msgs_.pop_front();
		}

	}

}
cpp 复制代码
//测试主程序
/*

1、封装线程基类XThread控制线程启动和停止;
2、模拟消息服务器线程,接收字符串消息,并模拟处理;
3、通过Unique_lock和mutex互斥方位list<string> 消息队列
4、主线程定时发送消息给子线程;

*/

#include "XMsgSever.h"
#include <sstream>
using namespace std;

int main()
{
	XMsgSever server;
	server.Start();//启动子线程,调了Main入口,进入死循环消费信息了
	for (int i = 0; i < 10; i++)
	{
		stringstream ss;
		ss << "msg: " << i + 1;
		server.SendMsg(ss.str());
		this_thread::sleep_for(500ms);
	}
	server.Stop();
	printf("All done!\n");

	return 0;
}

运行结果:

相关推荐
FQNmxDG4S3 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
前端老石人3 小时前
HTML 字符引用完全指南
开发语言·前端·html
matlab_xiaowang4 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
虹科网络安全4 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje4 小时前
Java语法进阶
java·开发语言·jvm
汉克老师4 小时前
GESP2025年3月认证C++五级( 第三部分编程题(1、平均分配))
c++·算法·贪心算法·排序·gesp5级·gesp五级
老前端的功夫5 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287925 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
止语Lab5 小时前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang
yaoxin5211235 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python