#include <iostream>
#include <mutex>
#include <list>
#include <map>
#include <string>
#include <thread>
#include <condition_variable>
using namespace std;
class Conditional
{
public:
void inMsgRecvQueue()
{
for (int i = 0; i < 10000; i++)
{
cout << "插入一个元素" << i << endl;
std::unique_lock<std::mutex> Mutex_Quique(m_Thread_Mutex);
m_msgRecvQueue.push_back(i);
m_condition.notify_one(); //条件变量为真 通知调用wait函数的线程进行解锁 执行代码
//m_condition.notify_all() 通知所有等待的变为真
}
return;
}
bool outMsgRecvProc(int & command)
{
while (true)
{
std::unique_lock<std::mutex> Mutex_Quique(m_Thread_Mutex);
// 等待上边调用notify_one函数的通知, 如果没有通知它会自动解锁的 因为上边用到了类模板自动上锁,如果不自动解锁,上边的代码执行不了
#if 0
捕获列表 作用
[a] a为值传递
[a, &b] a为值传递,b为引用传递
[&] 所有变量都用引用传递。当前对象(即this指针)也用引用传递。
[=] 所有变量都用值传递。当前对象用引用传递。
#endif
m_condition.wait(Mutex_Quique, [&] //lambda表达式是一个匿名函数
{
if (!m_msgRecvQueue.empty())
return true;
return false;
});
#if 0
//for (auto it = m_msgRecvQueue.begin(); it != m_msgRecvQueue.end(); ++it)
//C++11遍历容器的方法之一,只能是只读的
for (auto n : m_msgRecvQueue)
{
//cout << n << endl;
}
//加上引用就可以对容器内的值进行修改
for (auto &n : m_msgRecvQueue)
{
n = 999999;
cout << n << endl;
}
#endif
command = m_msgRecvQueue.front();
m_msgRecvQueue.pop_front();
cout << "取出一个元素为" << command << endl;
Mutex_Quique.unlock(); //这需要提前解锁,不用调用自动解锁析构函数 因为下边可以有需要长时间处理的代码
//需要长时间处理的代码
}
}
void outMsgRecvQueue()
{
int command = 0;
for (int i = 0; i < 10000; i++)
{
bool result = outMsgRecvProc(command);
if (result)
{
cout << "取出一个元素" << command << endl;
}
else
{
cout << "当前消息队列为空" << endl;
}
}
}
public:
map<int, string> m_TestDataMap;
private:
list<int> m_msgRecvQueue;
std::mutex m_Thread_Mutex;
std::condition_variable m_condition; //条件变量对象
};
#if 0
// 禁止类被继承的关键字
class A final
{
};
class V : public A
{
};
#endif
int main(void)
{
#if 0
条件变量
std::condition_variable实际上是一个类, 是一个和条件相关的类, 说白了就是在等一个条件达成
C++中,一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。它与普通函数不同的是,lambda必须使用尾置返回来指定返回类型。
#endif
Conditional oTestObj;
#if 0
oTestObj.m_TestDataMap[0] = "0000";
oTestObj.m_TestDataMap[1] = "1111";
oTestObj.m_TestDataMap[2] = "2222";
oTestObj.m_TestDataMap[3] = "3333";
for (auto &n : oTestObj.m_TestDataMap)
{
n.second = "99999";
cout << n.second << endl;
}
#endif
std::thread InThread(&Conditional::inMsgRecvQueue, &oTestObj);
std::thread OutThread(&Conditional::outMsgRecvQueue, &oTestObj); //第二个参数是引用,才能保证线程中创建的是同一个对象
OutThread.join();
InThread.join();
return 0;
}