当前位置: 首页 > news >正文

循环队列和阻塞有什么关系?和生产者消费者模型又有什么关系?阻塞队列和异步日志又有什么关系

### 循环队列和阻塞队列

#### 循环队列
- **定义**: 一个固定大小的数组,通过两个指针(`front` 和 `back`)管理队列的头部和尾部元素。
- **特点**:
  - **循环性**: 当指针到达数组的末尾时,可以回绕到数组的开头,从而利用数组的全部空间。
  - **空间效率**: 使用固定大小的数组,避免了动态内存分配和释放带来的开销。

#### 阻塞队列
- **定义**: 一种线程安全的队列,在队列为空时尝试出队的线程会被阻塞,在队列已满时尝试入队的线程也会被阻塞。
- **特点**:
  - **线程安全**: 使用互斥锁和条件变量来保证多线程环境下的安全访问。
  - **阻塞机制**: 当队列为空或已满时,通过条件变量阻塞相应的线程,直到队列状态发生改变。

### 阻塞队列与生产者-消费者模型

#### 生产者-消费者模型
- **定义**: 一种经典的多线程同步模型,通常涉及两个角色:生产者和消费者。
  - **生产者**: 负责生产数据并将其放入队列。
  - **消费者**: 负责从队列中取出数据进行处理。
- **特点**:
  - **解耦**: 生产者和消费者通过共享队列进行数据交换,彼此之间解耦。
  - **同步**: 使用阻塞队列来实现生产者和消费者之间的同步。

### 阻塞队列与异步日志系统

#### 异步日志系统
- **定义**: 一种日志记录系统,其中日志记录操作与业务逻辑操作分离,通过异步机制提高性能。
- **特点**:
  - **非阻塞**: 业务逻辑线程将日志消息放入队列后立即返回,而不是等待日志写入完成。
  - **后台处理**: 专门的日志线程从队列中取出日志消息并写入日志文件。

#### 阻塞队列在异步日志系统中的应用
- **队列**: 用于存放日志消息。
- **生产者**: 业务逻辑线程,将日志消息放入队列。
- **消费者**: 日志处理线程,从队列中取出日志消息并写入日志文件。
- **同步**: 通过阻塞队列实现生产者和消费者的同步,确保日志消息不会丢失且处理有序。

### 代码分析

- **构造函数**: 初始化队列的最大大小和内部数组。
- **析构函数**: 销毁队列,释放内存。
- **清空队列**: 清空队列内容并重置指针。
- **检查队列状态**: 判断队列是否为空或已满。
- **获取队首和队尾元素**: 安全地获取队列的首尾元素。
- **入队和出队操作**: 提供线程安全的入队和出队操作,使用条件变量实现阻塞机制。

总的来说,这个阻塞队列通过互斥锁和条件变量,实现了多线程环境下的安全访问和同步机制,可以用于生产者-消费者模型中,实现高效的异步日志系统。

 
#ifndef BLOCK_QUEUE_H
#define BLOCK_QUEUE_H
 
#include<iostream>
#include<stdio.h>
#include<pthread.h>
#include<sys/time.h>
#include"../lock/locker.h"
 
using namespace std;
 
template<class T>
class block_queue{
public:
 
    /*初始化阻塞队列*/
    block_queue(int max_size) {
        if (max_size <= 0) {
            exit(-1);
        }
 
        m_max_size = max_size;
        T* m_array = new T[max_size];
        m_size = 0;
        m_front = -1;
        m_back = -1;
    }
 
    /*删除new出的T数组*/
    ~block_queue() {
        m_mutex.lock();
        if (m_array != NULL) {
            delete []m_array;
        }
        m_mutex.unlock();
    }
 
    /*清空队列*/
    void clear() {
        m_mutex.lock();
        m_size = 0;
        m_front = -1;
        m_back = -1;
        m_mutex.unlock();
    }
 
    /*判断队列是否已满*/
    bool full() {
        m_mutex.lock();
        if (m_size >= m_max_size) {
            m_mutex.unlock();
            return true;
        }
        m_mutex.unlock();
        return false;
    }
 
    /*判断队列是否为空*/
    bool empty() {
        m_mutex.lock();
        if (m_size == 0) {
            m_mutex.unlock();
            return true;
        }
        m_mutex.unlock();
        return false;
    }
 
    /*获得队首元素*/
    bool front(T &value) {
        m_mutex.lock();
        /*注意下面的if判断不能用empty,因为empty函数也有加锁操作,加两次锁会导致死锁*/
        if (size == 0) {
            m_mutex.unlock();
            return false;
        }
        //TODO:个人感觉这行逻辑出错,后面部分是原代码  value = m_array[m_front];
        value = m_array[(m_front + 1) % m_max_size];
        m_mutex.unlock();
        return true;
    }
 
    /*获得队尾元素*/
    bool back(T& value) {
        m_mutex.lock();
        if (size == 0) {
            m_mutex.unlock();
            return false;
        }
        value = m_array[m_back];
        m_mutex.unlock();
        return true;
    }
 
    int size() {
        int tmp = 0;
        m_mutex.lock();
        tmp = m_size;
        m_mutex.unlock();
        return tmp;
    }
 
    int max_size() {
        int tmp = 0;
        m_mutex.lock();
        tmp = m_max_size;
        m_mutex.unlock();
        return tmp;
    }
 
    /*往队列中添加元素前需要先将所有使用队列的线程先唤醒*/
    /*阻塞队列封装了生产者消费者模型,调用push的是生产者,也就是工作线程*/
    bool push(T& item) {
        m_mutex.lock();
        if (m_size >= m_max_size) {
            cond.broadcast();
            m_mutex.unlock();
            return false;
        }
 
        m_back = (m_back + 1) % m_max_size;
        m_array[m_back] = item;
        m_size++;
 
        cond.broadcast();
        m_mutex.unlock();
        return true;
    }
 
    /*调用pop的是消费者,负责把生产者的内容写入文件*/
    bool pop(T& item) {
        m_mutex.lock();
        while (m_size <= 0) {
            if (!cond.wait(m_mutex.get())) {
                m_mutex.unlock();
                return false;
            }
        }
 
        m_front = (m_front + 1) % m_max_size;
        item = m_array[m_front];
        m_size--;
        m_mutex.unlock();
        return true;
    }
 
    bool pop(T& item,int ms_timeout) {
        struct timespec t = {0,0};//tv_sec :从1970年1月1日 0点到现在的秒数 tv_nsec:tv_sec后面的纳秒数
        struct timeval now = {0,0};//tv_sec: 从1970年1月1日 0点到现在的秒数 tu_usec:tv_sec后面的微妙数
        gettimeofday(&now,nullptr);
        m_mutex.lock();
        if (m_size <= 0) {
            t.tv_sec = now.tv_sec + ms_timeout/1000;
            t.tv_nsec = (ms_timeout % 1000) * 1000;
            if (!m_cond.timewait(m_mutex.get(), t)) {
                m_mutex.unlock();
                return false;
            }
        }
        //TODO:这一块代码的意义不知道在哪里,留着DEBUG
        if (m_size <= 0) {
            m_mutex.unlock();
            return false;
        }
        m_front = (m_front + 1) % m_max_size;
        item = m_array[m_front];
        m_size--;
        m_mutex.unlock();
        return true;
    }
 
private:
    locker m_mutex;
    cond m_cond;
 
 
    T* m_array;
    int m_max_size;
    int m_size;
    int m_front;
    int m_back;
};
 
#endif

相关文章:

循环队列和阻塞有什么关系?和生产者消费者模型又有什么关系?阻塞队列和异步日志又有什么关系

### 循环队列和阻塞队列 #### 循环队列 - **定义**: 一个固定大小的数组&#xff0c;通过两个指针&#xff08;front 和 back&#xff09;管理队列的头部和尾部元素。 - **特点**: - **循环性**: 当指针到达数组的末尾时&#xff0c;可以回绕到数组的开头&#xff0c;从而利…...

物理笔记-八年级上册

0.梦开始的地方 物理研究什么&#xff1f; 电学&#xff0c;力学&#xff0c;声学&#xff0c;光学&#xff0c;热学。 1.1.1长度的单位 国际基本单位制 单位转换 魔法记忆&#xff1a;千米-米-毫米-微米-纳米&#xff08;进率都是1000&#xff09; 单位换算计算方法 用科学…...

QT键盘和鼠标事件

这些事件都在QWidget 中的保护成员方法中 都是虚函数在头文件中声明了 需要类外重现实现 如果头文件中声明 类外无实现就会报错 void Widget::keyPressEvent(QKeyEvent *event) {switch (event->key()) {//获取按键case Qt::Key_W://按键wqDebug()<<"按下w"…...

文件Io编程基础

1. 标准I/O (stdio.h) stdio.h 是标准C库的头文件&#xff0c;包含了输入输出函数的声明。位置&#xff1a;/usr/include/stdio.h 2. 文件I/O操作步骤 打开文件: 使用 fopen 函数&#xff0c;返回 FILE* 指针。读/写操作: 使用 fread、fwrite、fgets、fputs、fprintf、fscan…...

本地项目提交到Gitee

在项目目录 右键 git bash here 可以在黑屏输入命令 也可以在项目里面 命令都是一样的 要排除哪些 git add . 添加所有文件 git commit -m "Initial commit" 提交到本地 git remote add origin https://gitee.com/xxxx/xxxx.git 添加远程仓库 …...

有了谷歌账号在登录游戏或者新APP、新设备时,要求在手机上点击通知和数字,怎么办?

有的朋友可能遇到过&#xff0c;自己注册或购买了谷歌账号以后&#xff0c;在自己的手机上可以正常登录&#xff0c;也完成了相关的设置&#xff0c;看起来一切都很完美&#xff0c;可以愉快地玩耍了。 但是&#xff0c;随后要登录一个游戏的时候&#xff08;或者登录一个新的…...

rsyslog如何配置日志轮转

以下是在 Linux 系统中配置 rsyslog 日志轮转策略的一般步骤&#xff1a; 编辑 rsyslog 的配置文件&#xff0c;通常为 /etc/rsyslog.conf 或 /etc/rsyslog.d/*.conf 。 在配置文件中添加类似以下的日志轮转配置示例&#xff1a; $template myLogs,"/var/log/mylog-%Y%m%d…...

LLM推理入门实践:基于 Hugging Face Transformers 和 Qwen2模型 进行文本问答

文章目录 1. HuggingFace模型下载2. 模型推理&#xff1a;文本问答 1. HuggingFace模型下载 模型在 HuggingFace 下载&#xff0c;如果下载速度太慢&#xff0c;可以在 HuggingFace镜像网站 或 ModelScope 进行下载。 使用HuggingFace的下载命令&#xff08;需要先注册Huggin…...

python:YOLO格式数据集图片和标注信息查看器

作者&#xff1a;CSDN _养乐多_ 本文将介绍如何实现一个可视化图片和标签信息的查看器&#xff0c;代码使用python实现。点击下一张和上一张可以切换图片。 文章目录 一、脚本界面二、完整代码 一、脚本界面 界面如下图所示&#xff0c; 二、完整代码 使用代码时&#xff0…...

AGI思考探究的意义、价值与乐趣 Ⅴ

搞清楚模型对知识或模式的学习与迁移对于泛化意味什么&#xff0c;或者说两者间的本质&#xff1f;相信大家对泛化性作为大语言模型LLM的突出能力已经非常了解了 - 这也是当前LLM体现出令人惊叹的通用与涌现能力的基础前提&#xff0c;这里不再过多赘述&#xff0c;但仍希望大家…...

c++: mangle命名规则

其实可用根据binutils/c++filt的源代码看。找到mangle的命名规则, 但是从网上找到了一个总结,但是github有时候上不去,摘录再次。 https://github.com/gchatelet/gcc_cpp_mangling_documentation https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling 举例: _ZN8…...

系统化学习 H264视频编码(05)码流数据及相关概念解读

说明&#xff1a;我们参考黄金圈学习法&#xff08;什么是黄金圈法则?->模型 黄金圈法则&#xff0c;本文使用&#xff1a;why-what&#xff09;来学习音H264视频编码。本系列文章侧重于理解视频编码的知识体系和实践方法&#xff0c;理论方面会更多地讲清楚 音视频中概念的…...

【VMware】如何演示使用U盘在VMware虚拟机上安装Windows11

一、前置准备 在开始使用U盘演示在VMware虚拟机上装Windows11前&#xff0c;我们需要做以下前置的准备&#xff1a; 已制作好的Windows引导盘&#xff1b;WMware软件 如何制作Windows引导盘&#xff1f; 推荐参考&#xff1a; 【建议收藏】2024年最新Windows系统重装教程&…...

HanLP和Jieba区别

HanLP和Jieba都是中文分词工具&#xff0c;但它们在多个方面存在区别。以下是对两者区别的详细分析&#xff1a; 一、开发背景与语言支持 HanLP&#xff1a;由大连理工大学自然语言处理与社会人文计算实验室开发&#xff0c;是一个开源的自然语言处理工具包。它主要使用Java语…...

荒原之梦考研:考研二战会很难吗?

考研二战是不是很难&#xff0c;其实很大程度上取决于我们自己&#xff0c;我们能否认清自己的优势&#xff0c;能否指定和执行合理的计划&#xff0c;有没有强大的心理支撑等&#xff0c;都是决定考研二战能否成功&#xff0c;或者能否比较轻松的成功的关键。 在本文中&#…...

【Git企业级开发实战指南①】Git安装、基本操作!

目录 一、Git是什么&#xff1f;1.1特点1.2功能1.3基本概念 二、Git安装2.1Ubuntu下安装2.2Centos下安装Git 三、Git基本操作3.1创建git本地仓库3.2配置Git3.3 工作区&暂存区&版本库3.4 实操案例3.4.1添加文件 3.5 修改文件3.6版本回退3.7查看历史操作日志3.7撤销修改3…...

Leetcode 3239. Minimum Number of Flips to Make Binary Grid Palindromic I

Leetcode 3239. Minimum Number of Flips to Make Binary Grid Palindromic I 1. 解题思路2. 代码实现 题目链接&#xff1a;3239. Minimum Number of Flips to Make Binary Grid Palindromic I 1. 解题思路 这一题思路上的话就是分别考察一下把所有行都变成回文所需要的fli…...

C++面试基础算法的简要介绍

C是一种广泛使用的编程语言&#xff0c;尤其在算法和数据结构的实现中占据重要地位。以下是对C基础算法的一些介绍&#xff0c;涵盖了排序、查找、搜索算法以及基本的遍历算法等方面。 排序算法 快速排序&#xff08;Quick Sort&#xff09; 快速排序是一种分而治之的排序算法…...

【Linux网络编程】套接字Socket(UDP)

网络编程基础概念&#xff1a; ip地址和端口号 ip地址是网络协议地址&#xff08;4字节32位&#xff0c;形式&#xff1a;xxx.xxx.xxx.xxx xxx在范围[0, 255]内&#xff09;&#xff0c;是IP协议提供的一种统一的地址格式&#xff0c;每台主机的ip地址不同&#xff0c;一个…...

jvm方法返回相关指令ireturn,areturn,return等分析

正文 看图&#xff1a; 做的事情如下: 1:弹出当前的方法栈帧 2:获取上一个方法 3:从当前方法的操作数栈中获取执行结果,并推送到上一个方法的操作数栈中对应的伪代码&#xff1a; Override public void execute(Frame frame) {Thread thread frame.thread();Frame curren…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...