C++多线程编程(第三章 案例3:把案例1改装成案例2的条件变量多线程方式)

由于案例1采用等待循环方式进行写入,如果更换成案例2的条件多线程方式,效率会大大增加,下面开始写出新的代码吧

主函数

/*

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

*/

#include "XMsgSever.h"
#include 
#include 

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

XMsgSever类头文件,主要增加了Stop()函数重写部分

//XMsgSever.h
#pragma once
#include "XThread.h"
#include 
#include 
class XMsgSever:public XThread
{
public:
	//给当前线程发消息
	void SendMsg(std::string msg);

	void Stop() override;//在子函数中重载

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

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

	std::mutex mux_;//互斥访问消息队列
	std::condition_variable cv_;//条件变量

};


XMsgSever类cpp文件,主要更改了类中的Main()函数,等待部分,使用了条件变量

//XMsgSever.cpp
#include "XMsgSever.h"
#include 

using namespace std;


void XMsgSever::SendMsg(std::string msg)
{//消息生产者
	
	unique_lock<mutex> lock(mux_);//为了保证list的线程安全,加锁
	msgs_.push_back(msg);
	lock.unlock();
	cv_.notify_one();//通知一个入口函数进行
}

void XMsgSever::Stop()
{
	//条件变量
	is_exit_ = true;
	cv_.notify_all();//通知所有线程,避免锁死了
	Wait();

}

void XMsgSever::Main()
{//消息消费者
	while (!is_exit())
	{
		//this_thread::sleep_for(10ms);
		unique_lock<mutex> lock(mux_);
		//cv_.wait(lock);//条件变量等待,条件满足就直接执行。如果这样写,最后可能一直阻塞在这里
		cv_.wait(lock, [this] {
			cout << "wait cv" << endl;
			if (is_exit())return true;//如果退出了,需要退出

			return !msgs_.empty(); //有内容,返回false
			});//条件变量等待,条件满足就直接执行

		if (msgs_.empty())
		{//如果没有消息,则continue
			continue;
		}
		while (!msgs_.empty())
		{//消息处理业务逻辑
			cout << "recv: " << msgs_.front().c_str() << endl;
			msgs_.pop_front();
		}

	}

}

XThread 类头文件中将is_exit_变量设置为了protected,为了在子类中可以访问这个变量

//XThread.h

#pragma once
#include 

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

protected:
	bool is_exit_ = false;//放到这里来,派生类可以访问这个变量

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

};


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

程序可以顺利执行完,执行效果如下图
C++多线程编程(第三章 案例3:把案例1改装成案例2的条件变量多线程方式)_第1张图片

你可能感兴趣的:(多线程,C++,笔记心得,c++,开发语言)