题目
实现一个带高水位标的线程安全的队列。
1)当队列中数据数量大于等于高水位标时,阻塞入队的操作
2)当队列中的数据小于高水位标时,入队不受阻塞
代码
ThreadSafetyQueue.h
#pragma once
#include <condition_variable>
#include <mutex>
#include <deque>
template<class T>
class ThreadSafetyQueue
{
public:
typedef std::unique_lock<std::mutex> TLock;
//maxCapacity为-1,代表队列无最大限制
explicit ThreadSafetyQueue(const int maxCapacity = -1) :m_maxCapacity(maxCapacity){}
size_t size()
{
TLock lock(m_mutex);
return m_list.size();
}
void push_back(const T& item)
{
TLock lock(m_mutex);
if (true == hasCapacity()) // 判断有无高水位标,无则可一直push
{
while (m_list.size() == m_maxCapacity)
{
m_notFull.wait(lock);
}
}
m_list.push_back(item);
std::cout << item << "进去了" << std::endl;
m_notEmpty.notify_all(); // 通知其他线程此时队列非空,即可进行pop操作
}
T pop()
{
TLock lock(m_mutex);
while (m_list.empty())
{
m_notEmpty.wait(lock);
}
T temp = *m_list.begin();
m_list.pop_front();
m_notFull.notify_all();
lock.unlock();
return temp;
}
bool empty()
{
TLock lock(m_mutex);
return m_list.empty();
}
bool full()
{
if (false == hasCapacity) // 无水位标则一直未满
{
return false;
}
TLock lock(m_mutex);
return m_list.size() >= m_maxCapacity;
}
private:
bool hasCapacity() const
{
return m_maxCapacity > 0;
}
typedef std::deque<T> TList;
TList m_list;
const int m_maxCapacity;
std::mutex m_mutex;
std::condition_variable m_notEmpty;
std::condition_variable m_notFull;
};
test.cpp
#include <iostream>
#include <thread>
#include <stdio.h>
#include "ThreadSafetyQueue.h"
#include <windows.h>
using namespace std;
typedef ThreadSafetyQueue<int> TQueue;
void produce(TQueue& queue)
{
const int num = 9;
for (int i = 0; i < num; ++i)
{
queue.push_back(i);
}
}
void consume(TQueue& queue)
{
while (false == queue.empty()) //非空 empty返回-1 即等于false 则pop_front
{
int tmp = queue.pop();
cout << tmp << "出来了" << endl;
Sleep(2000);
}
}
int main()
{
TQueue queue(2);
std::thread t1(produce, std::ref(queue));
std::thread t2(consume, std::ref(queue));
t2.join();
t1.join();
return 0;
}
代码阅读助力tips
1、thread类的构造函数是使用可变参数模板实现的,也就是说,可以传递任意个参数,第一个参数是线程的入口函数(可调用对象),而后面的若干个参数是该函数的参数。
2、unique_lock提供了lock()和unlock()接口,能记录现在处于上锁还是没上锁状态
3、condition_variable有两个重要的接口,notify_all()和wait(),wait()可以让线程陷入休眠状态,notify_all()唤醒处于wait中的所有条件变量。