发送消息时序图

news2024/10/6 20:33:00

内窥镜消息队列发送消息原理

目的

有一个多线程的Java应用程序,使用消息队列来处理命令

时序图

在这里插入图片描述

@startuml

actor User
participant "sendCmdWhiteBalance()" as Controller
participant CommandConsumer
participant MessageQueue

User -> Controller: 调用sendCmdWhiteBalance()

Controller -> MessageQueue: 将白平衡命令加入队列
activate MessageQueue

Controller -> CommandConsumer: 等待命令完成
activate CommandConsumer

CommandConsumer -> MessageQueue: 从队列中获取命令
MessageQueue -> CommandConsumer: 返回命令
CommandConsumer -> CommandConsumer: 执行命令
CommandConsumer -> Controller: 命令执行完成
deactivate CommandConsumer

Controller -> User: 返回成功响应

@enduml

线程安全和性能优化

使用阻塞队列(ArrayBlockingQueue)

使用ArrayBlockingQueue是因为它是一种线程安全的队列数据结构,它在多线程环境中提供了同步。

它的核心原理是基于锁和条件变量,它能够安全地协调不同线程之间的操作,确保数据的正确性。这是在多线程编程中一种重要的工具,它避免了显式的锁管理,降低了错误的可能性,提高了代码的可维护性。

使用blockingQueue.take()

调用blockingQueue.take()的主要目的是防止线程空转(busy-waiting)。

在没有消息进入队列的情况下,如果你使用简单的轮询(如poll()或isEmpty()检查),线程可能会在空循环中浪费大量的CPU时间。而take()方法会使线程在队列为空时进入阻塞状态,直到队列中有数据可以被取出。这降低了线程的 CPU 消耗,有效地减少了开销,使得线程能够更有效地等待新消息。

Java代码

下面是我的代码
@Component
@Slf4j
public class QueueJob {
    @PostConstruct
    public void QueueJob() {
        log.info("消费者开启****************************************************************************************************");

        if (System.getProperty("os.name") != null && System.getProperty("os.name").toLowerCase().startsWith("windows")) {
            return;
        }
        log.info("消费者开启");
        // 创建消息队列 (MessageQueue) 实例和消费者线程 (CommandConsumer)
        CommandConsumer commandConsumer = new CommandConsumer(messageQueue);
        commandConsumer.start();
    }

}


@Slf4j
public class CommandConsumer extends Thread {
    private final MessageQueue messageQueue;

    public CommandConsumer(MessageQueue messageQueue) {
        log.info("放入参数");
        this.messageQueue = messageQueue;
    }

    @Override
    public void run() {
        log.info("进入消费者模块中***********************************");
        while (true) {
            /**
             * 初始化完成后在执行命令
             * @author lst
             * @date 2023/8/8 9:18
             */
            if (!initStatus.get()) {
                continue;
            }
            log.info("run****************************************");
            CommandQueue commandQueue;
            try {
                commandQueue = messageQueue.takeFromQueue();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (commandQueue != null) {
                // 调用 sendMsg 方法发送指令,等待响应成功
                try {
                    log.info("sendMsg***********************************");
                    sendMsg(commandQueue.getCommand());
                    log.info("success***********************************");
                } catch (Exception e) {
                    catchSendMsgException(commandQueue.getMethod(), e);
                } finally {
                    handleCountDownLatch(commandQueue.getMethod());
                }

            }
        }
    }

@Slf4j
public class MessageQueue {
    /**
     * 顺序发送
     * 有应答才能发送下一条指令
     *
     * @author lst
     * @date 2023/8/7 13:45
     * @param null
     * @return null
     */
    private final BlockingQueue<CommandQueue> blockingQueue = new ArrayBlockingQueue<>(30, true);

    public void addToQueue(CommandQueue c) {
        log.info("添加队列中" + c.toString());
        if (!blockingQueue.offer(c)) {
            throw new IllegalStateException("队列已满,无法接受新的指令");
        }
    }

    public CommandQueue takeFromQueue() throws InterruptedException {
        return blockingQueue.take();
    }

    public int getQueueFreeSize() {
        return blockingQueue.remainingCapacity();
    }
}

基于上面我调用白平衡接口,会先将白平衡命令加入到阻塞队列中,阻塞队列中while循环持续消费
    @Operation(summary = "白平衡")
    @ConcurrentControl
    @GetMapping("sendCmdWhiteBalance")
    public CommonResult sendCmdWhiteBalance() throws InterruptedException {
        String key = WHITEBALANCE;
        messageQueue.addToQueue(new CommandQueue("sendCmdWhiteBalance", key));
        cmdWhiteBalanceCountDownLatch.await();
        cmdWhiteBalanceCountDownLatch = new CountDownLatch(1);
        if (cmdWhiteBalanceCountDownLatchException != null) {
            Exception e = cmdWhiteBalanceCountDownLatchException;
            cmdWhiteBalanceCountDownLatchException = null;
            throw new RuntimeException(e);
        }
        return CommonResult.success();
    }

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

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

相关文章

​左手 Serverless,右手 AI,7 年躬身的古籍修复之路

作者&#xff1a;宋杰 “AI 可以把我们思维体系当中&#xff0c;过度专业化、过度细分的这些所谓的知识都替代掉&#xff0c;让我们集中精力去体验自己的生命。我挺幸运的&#xff0c;代码能够有 AI 辅助&#xff0c;也能够有 Serverless 解决我的运营成本问题。Serverless 它…

mybatis拦截器源码分析

mybatis拦截器源码分析 拦截器简介 mybatis Plugins 拦截器由于Mybatis对数据库访问与操作进行了深度的封装,让我们应用开发效率大大提高,但是灵活度很差拦截器的作用:深度定制Mybatis的开发抛出一个需求 :获取Mybatis在开发过程中执行的SQL语句(执行什么操作获取那条SQL语句…

RK3562开发板:升级摄像头ISP,突破视觉体验边界

RK3562开发板作为深圳触觉智能新推出的爆款产品&#xff0c;采用 Rockchip 新一代 64 位处理器 RK3562&#xff08;Quad-core ARM Cortex-A53&#xff0c;主频最高 2.0GHz&#xff09;&#xff0c;最大支持 8GB 内存&#xff1b;内置独立的 NPU&#xff0c;可用于轻量级人工智能…

谷歌浏览查询http被自动转化成https导致页面读取失败问题处理

原因&#xff1a; 谷歌浏览器版本升级&#xff0c;安全问题考虑自动转化https 解决方案&#xff1a; 一、打开配置页面&#xff1a; chrome://flags/ 二、禁止自动转化

vue3_setup基础_渲染函数(ref,reactive)

一、setup语法糖 是什么&#xff1a;组合式Api &#xff08;vue2为option Api&#xff09; 来解决什么问题&#xff1a;使用&#xff08;data,computed,methonds,watch&#xff09;组件选项来组织逻辑通常都很有效。然而&#xff0c;当我们组件变的更大的时候&#xff0c;逻辑…

ansible的介绍安装与模块

目录 一、ansible简介 二、ansible特点 三、Ansible核心组件与工作原理 1、核心组件 2、工作原理 四、ansible的安装 五、ansible 命令行模块 1&#xff0e;command 模块 2&#xff0e;shell 模块 3&#xff0e;cron 模块 4&#xff0e;user 模块 5&#xff0e;group 模…

01 时钟配置初始化,debug

1. 开启debug series&#xff0c;否则只能下载一次&#xff0c;再次下载要配置boot 2.f0外部时钟配置 h750 配置 实测可用

股票印花税如何征收,万一免五的低费率成本计算以及券商选择

印花税国家收的&#xff0c;不管是深市沪市都收&#xff0c;如下图所示&#xff0c;可以看到&#xff0c;证券交易印花税自2008年9月之后改为单向收取&#xff0c;今年8月份更是降到了0.05%&#xff0c;也就是万分之5&#xff0c;以现在的视角看历史&#xff0c;在最早90年的千…

【数据结构】算法的空间复杂度

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 算法空间复杂度的定义 算法的时间复杂度和空间复杂度是度量算法好坏的两个重要量度,在实际写代码的过程中,我们完全可以用空间来换时间,比如说,我们要判断某某年是不是闰年,大…

基于Vue构建的快速开发框架

一、Vue结合低代码 "低代码"是一种快速开发应用的方法&#xff0c;它使开发者能够通过图形界面和预构建的块进行设计和构建&#xff0c;而不是手动编写大量的代码。这种方法被广泛用于快速应用开发、移动应用开发、业务流程管理和数据库应用开发等领域。 Vue.js 是一…

【Proteus仿真】【51单片机】智能语音家居陪护机器人

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用OLED液晶、按键、蜂鸣器、DS18B20温度传感器、人体红外传感器、语音识别模块、继电器、风扇、LED等。 主要功能&#xff1a; 系统运行后&#xff0…

Kafka生产者使用案例

1.生产者发送消息的过程 首先介绍一下 Kafka 生产者发送消息的过程&#xff1a; 1)Kafka 会将发送消息包装为 ProducerRecord 对象&#xff0c; ProducerRecord 对象包含了目标主题和要发送的内容&#xff0c;同时还可以指定键和分区。在发送 ProducerRecord 对象前&#xff0c…

FPGA面试题(7)

一.解释一下SPI的四种模式 01时钟极性CPOL空闲状态为低电平空闲状态为高电平时钟相位CPHA在第一个跳变沿采样在第二个跳变沿采样 模式CPOLCPHA描述模式000sclk上升沿采样&#xff0c;sclk下降沿发送模式101sclk上升沿发送&#xff0c;sclk下降沿采样模式210sclk上升沿发送&…

解决nav2_bringup tb3_simulation_launch.py 无法启动Gazebo的问题

方法 1 断网再开gazebo. 评价: 方便且有效, 但来回联网很麻烦 参考: https://blog.csdn.net/James___H/article/details/116906217 方法 2 断网能打开是因为gazebo软件开启时会自动从网络下载模型&#xff0c;下载过程必然漫长, 另外你懂的, 网络问题嘛, vpn也解决不了的话…

jmeter压测记录、使用方法

jmeter压测记录、使用方法 1、非gui方式执行压测命令2、压测命令输出解读 1、非gui方式执行压测命令 sh jmeter.sh -n -t test.jmx -l result.jtl2、压测命令输出解读 Active: 10 Started: 10 Finished: 0 Active: 10 表示一共10个活动&#xff08;正在进行的压测线程&#…

基于Cl2/BCl3电感偶联等离子体的氮化镓干蚀特性

引言 氮化镓(GaN)具有六方纤锌矿结构&#xff0c;直接带隙约为3.4eV&#xff0c;目前已成为实现蓝光发光二极管(led)的主导材料。由于GaN的高化学稳定性&#xff0c;在室温下用湿法化学蚀刻来蚀刻或图案化GaN是非常困难的。与湿法蚀刻技术相比&#xff0c;干法蚀刻技术可以提供…

前端axios下载导出文件工具封装

使用示例&#xff1a; import { fileDownload } from /utils/fileDownloadfileDownload({ url: process.env.VUE_APP_BASE_URL /statistic/pageList/export, method: post, data: data })工具类&#xff1a; import store from ../store/index import {getAccessToken } fro…

【Lombok的Bug记录】前端传的有值,但是到后端就全为空了

项目场景&#xff1a; 项目背景&#xff1a;使用Data注解标注类 问题描述 前端传的有值&#xff0c;但是到后端就全为空了 原因分析&#xff1a; AName和aName生成的set方法名是一样的&#xff0c;所以换名字就行了&#xff01; 解决方案&#xff1a; 属性不要写成xXxx的形式…

为什么手机会莫名多出许多软件?

许多手机用户都曾遭遇过这样的问题&#xff0c;他们在使用手机的过程中&#xff0c;突然发现手机屏幕上出现了一些未知的软件。这些软件并非他们主动下载的&#xff0c;但它们却显现在屏幕上。这些软件从何而来&#xff1f; 其实&#xff0c;这些软件往往是在浏览网页、阅读小…

spring 注入 当有两个参数的时候 接上面

新加一个int 型的 age 记得写getset方法和构造方法 &#xff08;&#xff08;&#xff08;&#xff08;&#xff08;&#xff08;&#xff08; 构造方法的作用——无论是有参构造还是无参构造&#xff0c;他的作用都是为了方便为对象的属性初始化值 构造方法是一种特殊的方…