消息队列的实现

8.8 消息队列

队列是一种先进先出的结构,消息队列是进程(线程)常用的一种方法,实现消息队列常用的方法:

(1)阻塞队列 (2)无锁队列 (3)环形队列

值得注意的是:在pop 和push 一定要使用while循环,避免虚假唤醒

8.8.1 阻塞队列

(1)pthread

实现阻塞队列使用生产者-消费者模式,使用步骤:

#include <pthread.h>
#include <queue>
//第一步,添加成员变量
std::queue<T> queue_;
int max_size_;
pthread_mutex_t mutex_;
pthread_cond_t condition_var_;
//第二步,实现push函数
void Push(const T& item) {pthread_mutex_lock(&mutex_);while (queue_.size() >= max_size_) {pthread_cond_wait(&condition_var_, &mutex_);}queue_.push(item);pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);
}
//第三步,实现pop函数T Pop() {pthread_mutex_lock(&mutex_);while (queue_.empty()) {pthread_cond_wait(&condition_var_, &mutex_);}T item = queue_.front();queue_.pop();pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);return item;}

示例代码:

#include <pthread.h>
#include <queue>template <typename T>
class BlockingQueue {
public:BlockingQueue() : max_size_(100) {pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&condition_var_, nullptr);}~BlockingQueue() {pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&condition_var_);}void Push(const T& item) {pthread_mutex_lock(&mutex_);while (queue_.size() >= max_size_) {pthread_cond_wait(&condition_var_, &mutex_);}queue_.push(item);pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);}T Pop() {pthread_mutex_lock(&mutex_);while (queue_.empty()) {pthread_cond_wait(&condition_var_, &mutex_);}T item = queue_.front();queue_.pop();pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);return item;}private:std::queue<T> queue_;int max_size_;pthread_mutex_t mutex_;pthread_cond_t condition_var_;
};

测试代码:

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>BlockingQueue<int> queue;void* ProducerThread(void* arg) {int thread_id = *static_cast<int*>(arg);for (int i = 1; i <= 5; ++i) {int item = thread_id * 10 + i;queue.Push(item);std::cout << "Producer " << thread_id << " produced: " << item << std::endl;sleep(1);}pthread_exit(nullptr);
}void* ConsumerThread(void* arg) {int thread_id = *static_cast<int*>(arg);for (int i = 1; i <= 5; ++i) {int item = queue.Pop();std::cout << "Consumer " << thread_id << " consumed: " << item << std::endl;sleep(2);}pthread_exit(nullptr);
}int main() {const int num_producers = 3;const int num_consumers = 2;std::vector<pthread_t> producer_threads(num_producers);std::vector<pthread_t> consumer_threads(num_consumers);for (int i = 0; i < num_producers; ++i) {int* thread_id = new int(i);pthread_create(&producer_threads[i], nullptr, ProducerThread, static_cast<void*>(thread_id));}for (int i = 0; i < num_consumers; ++i) {int* thread_id = new int(i);pthread_create(&consumer_threads[i], nullptr, ConsumerThread, static_cast<void*>(thread_id));}for (int i = 0; i < num_producers; ++i) {pthread_join(producer_threads[i], nullptr);}for (int i = 0; i < num_consumers; ++i) {pthread_join(consumer_threads[i], nullptr);}return 0;
}

**(2)STD **

示例代码:

#include <queue>
#include <mutex>
#include <condition_variable>template <typename T>
class BlockingQueue {
public:BlockingQueue() = default;void Push(const T& item) {std::unique_lock<std::mutex> lock(mutex_);while (queue_.size() >= max_size_) {condition_var_.wait(lock);}queue_.push(item);condition_var_.notify_one();}T Pop() {std::unique_lock<std::mutex> lock(mutex_);while (queue_.empty()) {condition_var_.wait(lock);}T item = queue_.front();queue_.pop();condition_var_.notify_one();return item;}private:std::queue<T> queue_;std::mutex mutex_;std::condition_variable condition_var_;const size_t max_size_ = 100; // 最大容量
};
8.8.2 环形队列

环形队列的特点:(1)固定容量 (2)前后指针 (3)循环存储

(1)pthread

示例代码:

#include <pthread.h>
#include <iostream>
#include <vector>template <typename T>
class CircularQueue {
public:CircularQueue(int capacity) : capacity_(capacity), front_(0), rear_(0), size_(0) {queue_.resize(capacity_);pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&condition_var_, nullptr);}~CircularQueue() {pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&condition_var_);}void Push(const T& item) {pthread_mutex_lock(&mutex_);while (size_ >= capacity_) {pthread_cond_wait(&condition_var_, &mutex_);}queue_[rear_] = item;rear_ = (rear_ + 1) % capacity_;++size_;pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);}T Pop() {pthread_mutex_lock(&mutex_);while (size_ <= 0) {pthread_cond_wait(&condition_var_, &mutex_);}T item = queue_[front_];front_ = (front_ + 1) % capacity_;--size_;pthread_cond_signal(&condition_var_);pthread_mutex_unlock(&mutex_);return item;}private:std::vector<T> queue_;int capacity_;int front_;int rear_;int size_;pthread_mutex_t mutex_;pthread_cond_t condition_var_;
};void* ProducerThread(void* arg) {CircularQueue<int>* queue = static_cast<CircularQueue<int>*>(arg);for (int i = 1; i <= 10; ++i) {queue->Push(i);std::cout << "Produced: " << i << std::endl;sleep(1);}return nullptr;
}void* ConsumerThread(void* arg) {CircularQueue<int>* queue = static_cast<CircularQueue<int>*>(arg);for (int i = 1; i <= 10; ++i) {int item = queue->Pop();std::cout << "Consumed: " << item << std::endl;sleep(2);}return nullptr;
}int main() {CircularQueue<int> queue(5);pthread_t producer_thread;pthread_create(&producer_thread, nullptr, ProducerThread, static_cast<void*>(&queue));pthread_t consumer_thread;pthread_create(&consumer_thread, nullptr, ConsumerThread, static_cast<void*>(&queue));pthread_join(producer_thread, nullptr);pthread_join(consumer_thread, nullptr);return 0;
}

(2)STD

示例代码:

#include <vector>
#include <mutex>
#include <condition_variable>template <typename T>
class CircularQueue {
public:CircularQueue(int capacity) : capacity_(capacity), front_(0), rear_(0), size_(0), queue_(capacity_) {}void Push(const T& item) {std::unique_lock<std::mutex> lock(mutex_);while (IsFull()) {condition_var_.wait(lock);}queue_[rear_] = item;rear_ = (rear_ + 1) % capacity_;++size_;condition_var_.notify_one();}T Pop() {std::unique_lock<std::mutex> lock(mutex_);while (IsEmpty()) {condition_var_.wait(lock);}T item = queue_[front_];front_ = (front_ + 1) % capacity_;--size_;condition_var_.notify_one();return item;}bool IsEmpty() const {return size_ == 0;}bool IsFull() const {return size_ == capacity_;}private:int capacity_;int front_;int rear_;int size_;std::vector<T> queue_;std::mutex mutex_;std::condition_variable condition_var_;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717969.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥ACM培训-实战1

前言&#xff1a; 今天老师没讲课&#xff0c;只让我们做了一下几道题目。 正文&#xff1a; Problem:A 小蓝与操作序列&#xff1a; #include<bits/stdc.h> using namespace std; stack<int> a; int main(){int n,flag1,ans;string cz;cin>>n;for(int i1;…

访问修饰符、Object(方法,使用、equals)、查看equals底层、final--学习JavaEE的day15

day15 一、访问修饰符 含义&#xff1a; 修饰类、方法、属性&#xff0c;定义使用的范围 理解&#xff1a;给类、方法、属性定义访问权限的关键字 注意&#xff1a; ​ 1.修饰类只能使用public和默认的访问权限 ​ 2.修饰方法和属性可以使用所有的访问权限 访问修饰符本类本包…

JetCache源码解析——API实现(持续更新中……)

在JetCache中不仅可以通过在类和接口的函数上使用注解Cached、CacheUpdate和CacheInvalidate等实现缓存加载、更新和删除操作&#xff0c;也支持通过调用API接口的形式来实现缓存的加载、更新和删除操作。 缓存接口 缓存接口的定义如下&#xff1a; /*** 缓存接口&#xff0…

【计算机网络】HTTPS 协议原理

https 一、HTTPS 是什么二、加密1. 加密概念2. 加密的原因3. 常见的加密方式&#xff08;1&#xff09;对称加密&#xff08;2&#xff09;非对称加密 三、数据摘要(数据指纹)四、HTTPS 的工作原理探究1. 只使用对称加密2. 只使用非对称加密3. 双方都使用非对称加密4. 非对称加…

Linux:kubernetes(k8s)部署CNI网络插件(4)

在上一章进行了node加入master Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;node节点加入master主节点&#xff08;3&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136420447?spm1001.2014.3001.5501 但是他们显示还是没准备好 看一下…

面试笔记系列五之MySql+Mybaits基础知识点整理及常见面试题

目录 Myibatis myibatis执行过程 mybatis的优缺点有哪些&#xff1f; mybatis和hibernate有什么区别&#xff1f; mybatis中#{}和${}的区别是什么&#xff1f; 简述一下mybatis插件运行原理及开发流程&#xff1f;&#xff08;插件四大天王&#xff09; mybatis的mapper没…

2.模拟问题——5.星期几与字符串对应

输入输出示例 输入&#xff1a; 9 October 2001 14 October 2001 输出&#xff1a; Tuesday Sunday 【原题链接】 字符串处理 C风格的字符串 字符数组&#xff0c;以’\0‘结尾建议在输入输出语句中使用 C风格的字符串 #include <string> using namespace std;初始化…

「优选算法刷题」:最长回文子串

一、题目 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba"…

【字符串】马拉车(Manacher)算法

本篇文章参考&#xff1a;比较易懂的 Manacher&#xff08;马拉车&#xff09;算法配图详解 马拉车算法可以求出一个字符串中的最长回文子串&#xff0c;时间复杂度 O ( n ) O(n) O(n) 因为字符串长度的奇偶性&#xff0c;回文子串的中心可能是一个字符&#xff0c;也可能是…

uniapp聊天记录本地存储(详细易懂)

目录 目录 1、通过websocket拿取数据 2、获取聊天数据 3、聊天信息存储 、更新 4、读取聊天记录 5、发送信息&#xff0c;信息获取 6、最终效果 1.聊天信息的存储格式 2、样式效果 写聊天项目&#xff0c;使用到了本地存储。需要把聊天信息保存在本地&#xff0c;实时获…

GPT对话知识库——ARM-Cortex架构分为哪几个系列?每个系列有几种工作模式?各种工作模式之间的定义和区别?每种架构不同的特点和应用需求?

提问模型&#xff1a;GPT-4-TURBO-PREVIEW 提问时间&#xff1a;2024.03.02 1&#xff0c;问&#xff1a; Cortex-M系列有几种工作模式 1&#xff0c;答&#xff1a; Cortex-M系列微控制器是ARM公司开发的一类低功耗、高性能的32位微处理器&#xff0c;广泛应用于嵌入式系统中…

Centos7使用man查找命令时,报错No manual entry for xxxx

Centos7使用man查找命令时&#xff0c;报错No manual entry for xxxx 在Linux中使用man指令查找指令信息时&#xff0c;报No manual entry for xxxx。 比如使用man指令查找sleep3号手册时&#xff0c;出现以下错误&#xff1a; 这是由于没有安装man-pages这个rpm包导致的&#…

掌握基本排序算法:冒泡、选择、插入和快速排序

在计算机科学的世界里&#xff0c;排序是一项基本而重要的操作。无论是数据库管理、搜索引擎&#xff0c;还是日常编程&#xff0c;高效的排序算法都是提高性能的关键。本文将介绍四种基本的排序算法&#xff1a;冒泡排序、选择排序、插入排序和快速排序&#xff0c;并探讨它们…

从0开始学习NEON(1)

1、前言 在上个博客中对NEON有了基础的了解&#xff0c;本文将针对一个图像下采样的例子对NEON进行学习。 学习链接:CPU优化技术 - NEON 开发进阶 上文链接:https://blog.csdn.net/weixin_42108183/article/details/136412104 2、第一个例子 现在有一张图片&#xff0c;需…

获取 Windows 通知中心弹窗通知内容(含工具汉化)

目录 前言 技术原理概述 测试代码和程序下载连接 本文出处链接&#xff1a;https://blog.csdn.net/qq_59075481/article/details/136440280。 前言 从 Windows 8.1 开始&#xff0c;Windows 通知现在以 Toast 而非 Balloon 形式显示&#xff08; Bollon 通知其实现在是应用…

在ubuntu上安装hadoop完分布式

准备工作 Xshell安装包 Xftp7安装包 虚拟机安装包 Ubuntu镜像源文件 Hadoop包 Java包 一、安装虚拟机 创建ubuntu系统 完成之后会弹出一个新的窗口 跑完之后会重启一下 按住首先用ctrlaltf3进入命令界面&#xff0c;输入root&#xff0c;密码登录管理员账号 按Esc 然后输入 …

数据结构常用的字符串函数(中英双释)

头文件&#xff1a;string.h 1.strchr const char * strchr ( const char * str, int character ); Locate first occurrence of character in string str C string. character Character to be located. Return Value A pointer to the first occurrence of character in s…

适用于恢复iOS数据的 10 款免费 iPhone 恢复软件

现在&#xff0c;您可以获得的 iPhone 的存储容量比大多数人的笔记本电脑和台式电脑的存储容量还要大。虽然能够存储数千张高分辨率照片和视频文件、安装数百个应用程序并随身携带大量音乐库以供离线收听固然很棒&#xff0c;但在一个地方拥有如此多的数据可能会带来毁灭性的后…

2.2_5 调度算法

文章目录 2.2_5 调度算法一、适用于早期的批处理系统&#xff08;一&#xff09;先来先服务&#xff08;FCFS&#xff0c;First Come First Serve&#xff09;&#xff08;二&#xff09;短作业优先&#xff08;SJF&#xff0c;Shortest Job First&#xff09;&#xff08;三&a…

SpringMVC总结

SpringMVC SpringMVC是隶属于Spring框架的一部分&#xff0c;主要是用来进行Web开发&#xff0c;是对Servlet进行了封装。 对于SpringMVC我们主要学习如下内容: SpringMVC简介 请求与响应 REST风格 SSM整合(注解版) 拦截器 SpringMVC是处理Web层/表现层的框架&#xff…