这个图可以解释阻塞队列要做什么,阻塞队列主要用于线程和线程之间的通信。当队列为空时,从队列中获取元素的线程将会被挂起;当队列是满时,往队列里添加元素的线程将会挂起。
#pragma once
#include <condition_variable>
#include <mutex>
#include <deque>
template<class T>
class BlockQueue
{
public:
typedef std::unique_lock<std::mutex> TLock;
//maxCapacity为-1,代表队列无最大限制
explicit BlockQueue(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())
{
while (m_list.size() >= m_maxCapacity)
{
m_notFull.wait(lock);
}
}
m_list.push_back(item);
m_notEmpty.notify_all();
}
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;
};
测试部分
#include <iostream>
#include <thread>
#include <stdio.h>
using namespace std;
typedef BlockQueue<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())
{
int tmp = queue.pop();
printf("%d\n", tmp);
std::this_thread::sleep_for(chrono::seconds(1));
}
}
int main()
{
TQueue queue(2);
std::thread t1(produce, std::ref(queue));
std::thread t2(consume, std::ref(queue));
std::thread t3(consume, std::ref(queue));
t3.join();
t2.join();
t1.join();
return 0;
}