BlockingQueue在多线程开发中几乎是离不开的,它可以理解为封装好的生产者与消费者的桥梁,其实它的数据结构同前文讲的Queue一样,只是在此基础之上加入了生产与消费者模式中的wait(阻塞等待,此方法会释放锁)和唤醒(notify)
JDK中提供的常用的BlockingQueue有ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue(优先级)
STL库中queue是链表结构的队列,当然也有提供dequeue(数组结构), priority_queue,这里只写一个用queue来实现的类,其他扩展同理,其实就是一些并发锁的使用
#include <queue>
#include <mutex>
template <class E>
class BlockingQueue {
private:
queue<E> _queue;
int capacity = INT_MAX;
condition_variable takeVariable, putVariable;
mutable mutex lock;
public:
BlockingQueue();
/**
*
* @param capacity 队列允许的最大值,在put时size()大于此值时,put方法将会wait
*/
BlockingQueue(int capacity);
/**
* size() == 0 时会阻塞
* @param e
* @return -1失败, 0成功
*/
int take(E &e);
/**
* size >= capacity时会阻塞
* @param e
* @return
*/
int put(const E &e);
bool empty() const;
unsigned int size() const;
void pop();
E back();
E front();
};
template <class E>
BlockingQueue<E>::BlockingQueue() {
}
template <class E>
BlockingQueue<E>::BlockingQueue(int capacity) : capacity(capacity) {
}
template <class E>
int BlockingQueue<E>::take(E &e) {
unique_lock<mutex> uniqueLock(lock);
while (_queue.empty()) {
takeVariable.wait(uniqueLock);
}
if (_queue.empty()) return -1;
e = _queue.front();
_queue.pop();
putVariable.notify_one();
return 0;
}
template <class E>
int BlockingQueue<E>::put(const E &e) {
unique_lock<mutex> uniqueLock(lock);
while (_queue.size() >= capacity) {
putVariable.wait(uniqueLock);
}
if (_queue.size() >= capacity) return -1;
_queue.push(e);
takeVariable.notify_one();
return 0;
}
template <class E>
bool BlockingQueue<E>::empty() const {
lock_guard<mutex> lockGuard(lock);
return _queue.empty();
}
template <class E>
unsigned int BlockingQueue<E>::size() const {
lock_guard<mutex> lockGuard(lock);//利用变量作用域创建加锁,析构自动解锁
return _queue.size();
}
template <class E>
void BlockingQueue<E>::pop() {
lock.lock();
_queue.pop();
lock.unlock();
}
template <class E>
E BlockingQueue<E>::back() {
lock_guard<mutex> lockGuard(lock);
return _queue.back();
}
template <class E>
E BlockingQueue<E>::front() {
lock_guard<mutex> lockGuard(lock);
return _queue.front();
}
网友评论