【多线程】阻塞队列的C++多线程 实现 BlockingQueue
阻塞隊(duì)列在存放和獲取隊(duì)列中的數(shù)據(jù)時(shí)需要使用多線程,一個(gè)線程專門負(fù)責(zé)向隊(duì)列中存放元素,另一個(gè)線程專門從隊(duì)列中獲取元素。也可多開辟跟多的線程進(jìn)行存取。
規(guī)范的方法也正是存放和獲取隊(duì)列元素分別在不同的線程中實(shí)現(xiàn)。
阻塞隊(duì)列實(shí)現(xiàn):
當(dāng)隊(duì)列為空時(shí),從隊(duì)列獲取元素的操作將會(huì)被阻塞,直到隊(duì)列中被放入了元素;
當(dāng)隊(duì)列滿時(shí),有兩種方案:
-
方案1: 往隊(duì)列里存放元素的操作也會(huì)被阻塞,直到有元素被從隊(duì)列中取出或者刪除。
具體方法:定義一個(gè)條件變量std::condition_variable not_full_;在存放操作時(shí),判斷隊(duì)列為滿時(shí),使用not_full_.wait(lock)阻塞線程;當(dāng)進(jìn)行刪除隊(duì)列元素的操作后,就使用not_full_.notify_all()來(lái)喚醒not_full_.wait(lock)的線程。【注意區(qū)分: 條件變量not_empty_是在獲取數(shù)據(jù)時(shí)判斷隊(duì)列是否為空,為空時(shí),使用not_empty_.wait(lock); ,當(dāng)有隊(duì)列有新數(shù)據(jù)進(jìn)來(lái)才會(huì)not_empty_.notify_all();喚醒not_empty_.wait(lock);的線程。 存放操作和獲取操作需要使用不同的條件變量進(jìn)行阻塞等待和喚醒】
-
方案2: 不使用阻塞,而是直接刪除隊(duì)列中最老的元素,刪除后就直接往隊(duì)列添加元素了。【本文示例就是方案2】
以上的操作都是基于不同的線程來(lái)說(shuō)的,線程在對(duì)阻塞隊(duì)列進(jìn)程操作時(shí)會(huì)被阻塞。
#pragma once#include <condition_variable> #include <deque> #include <mutex> #include <string> #include <thread> #include <list> #include <vector>template <typename T> class BlockingQueue {public:BlockingQueue(uint size) : size_(size) {}BlockingQueue() {}/*** @brief 向隊(duì)列中push_back一個(gè)元素* **/void put(const T x) {std::unique_lock<std::mutex> lock(mutex_);if (size_ != 0 && queue_.size() > size_) {queue_.pop_front();}queue_.push_back(std::move(x));not_empty_.notify_all(); //有新數(shù)據(jù)push進(jìn)來(lái)后就喚醒所有wait的線程}/*** @brief 獲取隊(duì)列中第一個(gè)元素(不是最新元素)* 元素一旦獲取,就從隊(duì)列中刪除* **/T take() {std::unique_lock<std::mutex> lock(mutex_);while (queue_.empty()) {not_empty_.wait(lock); //如果隊(duì)列為空,線程就在此阻塞掛起,等待喚醒}const T front = queue_.front();queue_.pop_front();return front;}/*** @brief 取出隊(duì)列中第一個(gè)元素(取出后就從隊(duì)列中刪除),并push_back到一個(gè)vector中* **/int take(std::vector<T> *v, size_t count) {std::unique_lock<std::mutex> lock(mutex_);while (queue_.empty()) {not_empty_.wait(lock); //如果隊(duì)列為空,線程就在此阻塞掛起,等待喚醒}while (!queue_.empty() && count--) {v->push_back(queue_.front());queue_.pop_front();}return v->size();}/*** @brief 根據(jù)索引獲取隊(duì)列中對(duì)應(yīng)元素* **/T get(size_t index) {std::unique_lock<std::mutex> lock(mutex_);while (queue_.empty()) {not_empty_.wait(lock);}return queue_.at(index);}size_t size() const {std::unique_lock<std::mutex> lock(mutex_);return queue_.size();}private:mutable std::mutex mutex_;std::condition_variable not_empty_;std::deque<T> queue_;// std::list<T> queue_;//雙向鏈表uint size_ = 0; };總結(jié)
以上是生活随笔為你收集整理的【多线程】阻塞队列的C++多线程 实现 BlockingQueue的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Linux】31. ffmpeg常用命
- 下一篇: 【数据结构与算法】5. C++中 lis