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

RocketMQ基础学习

前言:

        RocketMQ阿里开源的,一款分布式的消息中间件,它经过阿里的生产环境的高并发、高吞吐的考验,同时,还支持分布式事务等场景。RocketMQ使用Java语言进行开发,方便Java开发者学习源码。但是,RocketMQ设计相对复杂,官方文档不是很完善,不太适合中小公司引用。技多不压身,作为一个好的Coder,应该多学习一下优秀的框架。本篇主要介绍一下,RocketMQ的基础用法:

正文:

        这里我主要通过代码来介绍一下RocketMQ的使用,首先介绍一下RocketMQ的原生写法,然后介绍基于Springboot体系下,RocketMQ生产者的消息发送、消费者的消息接受等写法。

一、Java原生的消息发送与接收写法:

1. 生产者:

/*** 〈一句话功能简述〉<br>* 〈〉** @author hanxinghua* @create 2022/9/30* @since 1.0.0*/
@Slf4j
public class Producer {public static void main(String[] args) throws Exception {// 实例化消息生产者DefaultMQProducer producer = new DefaultMQProducer(RocketConstant.ORIGINAL_PRODUCER_GROUP);// 设置NameServer的地址producer.setNamesrvAddr(RocketConstant.NAME_SERVER_ADDR);// 启动Producer实例producer.start();// 创建消息,设置 Topic、Tag、keys、flag、消息体等Message message = new Message(RocketConstant.ORIGINAL_TOPIC, ("Hello RocketMQ").getBytes(RemotingHelper.DEFAULT_CHARSET));// 发送消息到一个BrokerSendResult sendResult = producer.send(message);// 通过sendResult返回消息是否成功送达log.info("消息发送成功:{}", sendResult);// 如果不再发送消息,关闭Producer实例。producer.shutdown();}}

2. 消费者:

/*** 〈一句话功能简述〉<br>* 〈〉** @author hanxinghua* @create 2022/9/30* @since 1.0.0*/
@Slf4j
public class Consumer {public static void main(String[] args) throws Exception {// 实例化消费者DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(RocketConstant.ORIGINAL_CONSUMER_GROUP);// 设置NameServer的地址consumer.setNamesrvAddr(RocketConstant.NAME_SERVER_ADDR);// 订阅一个或多个Topic,用Tag来过滤需要消费的消息,这里指定*表示接收所有Tag的消息consumer.subscribe(RocketConstant.ORIGINAL_TOPIC, "*");// 注册回调实现类来处理从broker拉取回来的消息consumer.registerMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> messageExts, ConsumeConcurrentlyContext context) {log.info("{}收到消息:{}", this.getClass().getSimpleName(), messageExts);// 标记该消息已经被成功消费return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});// 启动消费者实例consumer.start();log.info("消费者启动成功!");}
}

二、基于Springboot体系的消息发送写法:

1.普通消息发送:

        具体有三种形式,主要包括:同步、异步、单向。

    /*** 发送普通同步消息** @return*/@GetMapping("/sendMqBySync")@ResponseBodypublic Object sendMqBySync() {RocketMessage message = RocketMessage.builder().name("普通同步消息" + LocalDateTime.now()).build();// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.COMMON_TOPIC, message);return sendResult;}/*** 发送异步消息** @return*/@GetMapping("/sendMqByAsync")@ResponseBodypublic Object sendMqByAsync() {RocketMessage message = RocketMessage.builder().name("异步消息" + LocalDateTime.now()).build();// asyncSendrocketMQTemplate.asyncSend(RocketConstant.ASYNC_TOPIC, message, new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {// 处理相应的业务log.info("发送成功:{}", JSON.toJSONString(sendResult));}@Overridepublic void onException(Throwable throwable) {// 处理相应的业务log.info("发送异常:{}", throwable);}});return null;}/*** 发送单向消息* <p>* 这种方式主要用在不特别关心发送结果的场景,例如日志发送** @return*/@GetMapping("/sendMqByOneWay")@ResponseBodypublic Object sendMqByOneWay() {RocketMessage message = RocketMessage.builder().name("单向消息" + LocalDateTime.now()).build();// sendOneWayrocketMQTemplate.sendOneWay(RocketConstant.ONE_WAY_TOPIC, message);return null;}

2.顺序消息发送:

        具体有两种形式,主要包括:普通顺序、严格顺序。

    /*** 发送普通顺序消息** @return*/@GetMapping("/sendMqByOrder")@ResponseBodypublic Object sendMqByOrder() {List<SendResult> results = new ArrayList<>();for (int i = 0; i < 10; i++) {RocketMessage message = RocketMessage.builder().name("普通顺序消息" + LocalDateTime.now() + i).build();// syncSendOrderlySendResult sendResult = rocketMQTemplate.syncSendOrderly(RocketConstant.COMMON_TOPIC, message, "hashkey");results.add(sendResult);}return results;}/*** 发送严格顺序消息* <p>* 概念:* 顺序消息是一种对消息发送和消费顺序有严格要求的消息* <p>* 生产顺序性:* RocketMQ通过生产者和服务端的协议保障单个生产者串行地发送消息,并按序存储和持久化。如需保证消息生产的顺序性,则必须满足以下条件:* 单一生产者: 消息生产的顺序性仅支持单一生产者,不同生产者分布在不同的系统,即使设置相同的分区键,不同生产者之间产生的消息也无法判定其先后顺序。* 串行发送:生产者客户端支持多线程安全访问,但如果生产者使用多线程并行发送,则不同线程间产生的消息将无法判定其先后顺序。** @return*/@GetMapping("/sendMqByStrictOrder")@ResponseBodypublic Object sendMqByStrictOrder() {List<SendResult> results = new ArrayList<>();for (int i = 0; i < 10; i++) {RocketMessage message = RocketMessage.builder().name("严格顺序消息" + LocalDateTime.now() + i).build();// syncSendOrderlySendResult sendResult = rocketMQTemplate.syncSendOrderly(RocketConstant.STRICT_ORDER_TOPIC, message, "hashkey");results.add(sendResult);}return results;}

3. 延迟消息发送:

    /*** 发送延时消息* <p>* 延时消息的使用限制* private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"* 现在RocketMq并不支持任意时间的延时,需要设置几个固定的延时等级,从1s到2h分别对应着等级1到18,* 消息消费失败会进入延时消息队列** @return*/@GetMapping("/sendMqByDelay")@ResponseBodypublic Object sendMqByDelay() {RocketMessage message = RocketMessage.builder().name("延时消息" + LocalDateTime.now()).build();// syncSend(... int delayLevel)SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.DELAY_TOPIC, MessageBuilder.withPayload(message).build(), 2000, 4);return sendResult;}

4. 批量消息发送:

    /*** 批量发送消息* <p>* 在对吞吐率有一定要求的情况下,RocketMQ可以将一些消息聚成一批以后进行发送,* 可以增加吞吐率,并减少API和网络调用次数** @return*/@GetMapping("/sendMqByBatch")@ResponseBodypublic Object sendMqByBatch() {List<Message> messageList = new ArrayList<>();for (int i = 0; i < 10; i++) {RocketMessage message = RocketMessage.builder().name("批量消息" + LocalDateTime.now() + i).build();messageList.add(MessageBuilder.withPayload(message).build());}// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.COMMON_TOPIC, messageList);return sendResult;}

 5. 事务消息发送:

   /*** 发送事务消息(半消息)* <p>* 仅仅只是保证本地事务和MQ消息发送形成整体的原子性,而投递到MQ服务器后,* 并无法保证消费者一定能消费成功* <p>** @return*/@GetMapping("/sendMqByTx")@ResponseBodypublic Object sendMqByTx(Integer type, Integer msgKey) {String transactionId = UUID.randomUUID().toString();No6LocalTransactionOriginalSyntaxListener transactionListener = new No6LocalTransactionOriginalSyntaxListener();TransactionMQProducer producer = new TransactionMQProducer(RocketConstant.TX_PRODUCER_GROUP);try {producer.setTransactionListener(transactionListener);producer.setNamesrvAddr(RocketConstant.NAME_SERVER_ADDR);producer.start();log.info("transactionId is {}", transactionId);org.apache.rocketmq.common.message.Message msg = new org.apache.rocketmq.common.message.Message(RocketConstant.TX_TOPIC,("事务消息" + LocalDateTime.now()).getBytes(RemotingHelper.DEFAULT_CHARSET));msg.getProperties().put(RocketMQHeaders.TRANSACTION_ID, transactionId);msg.getProperties().put("type", String.valueOf(type));msg.getProperties().put("msgKey", String.valueOf(msgKey));SendResult sendResult = producer.sendMessageInTransaction(msg, null);return sendResult;} catch (Exception e) {e.printStackTrace();} finally {producer.shutdown();}return null;}

6. 带Tag消息发送:

    /*** 发送带Tag消息* <p>* Tag(标签)可以看作子主题,它是消息的第二级类型* 通过 RocketMQTemplate发送带Tag的消息,只需要将topic和tag中间通过【:】冒号连接即可** @return*/@GetMapping("/sendMqWithTag")@ResponseBodypublic Object sendMqWithTag() {RocketMessage message = RocketMessage.builder().name("tag消息" + LocalDateTime.now()).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.TAG_TOPIC + ":" + RocketConstant.TAG_EXPRESSION, message);return sendResult;}

三、基于Springboot体系的消息接收写法:

1. MessageModel(消息模型):

        消息模型有两种,主要包括:集群消费与广播消费

    /*** 发送集群或广播消息* <p>* 广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。** @param MessageModel 0:CLUSTERING   1:BROADCASTING* @return*/@GetMapping("/sendMqByMessageModel")@ResponseBodypublic Object sendMqByMessageModel(@RequestParam Integer MessageModel) {List<SendResult> results = new ArrayList<>();for (int i = 0; i < 10; i++) {if (MessageModel == 0) {RocketMessage message = RocketMessage.builder().name("消息模型-集群消费" + LocalDateTime.now() + i).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.COMMON_TOPIC, message);results.add(sendResult);} else {RocketMessage message = RocketMessage.builder().name("消息模型-广播消费" + LocalDateTime.now() + i).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.BROADCAST_TOPIC, message);results.add(sendResult);}}return results;}

2. ConsumeMode(消费模型):

        消费模型有两种,主要包括:并发消费与顺序消费

    /*** 并发消费与顺序消费** @param consumeMode 0:CONCURRENTLY  1:ORDERLY* @return*/@GetMapping("/sendMqByConsumeMode")@ResponseBodypublic Object sendMqByConsumeMode(Integer consumeMode) {List<SendResult> results = new ArrayList<>();for (int i = 0; i < 10; i++) {if (consumeMode == 0) {RocketMessage message = RocketMessage.builder().name("消费模型-并发消费" + LocalDateTime.now() + i).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.COMMON_TOPIC, message);results.add(sendResult);} else {RocketMessage message = RocketMessage.builder().name("消费模型-顺序消费" + LocalDateTime.now() + i).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.STRICT_ORDER_TOPIC, message);results.add(sendResult);}}return results;}

3. 消息过滤:

        消息过滤有两种方式,主要包括:Tag过滤与SQL92过滤

   /*** Tag过滤与SQL92过滤* <p>* Tag过滤:* 消费者订阅的Tag和发送者设置的消息Tag相互匹配,则消息被投递给消费端进行消费。* SQL92过滤:* 发送者设置Tag或自定义消息属性,消费者订阅满足SQL92过滤表达式的消息被投递给消费端进行消费。* 开启对SQL语法的支持(broker.conf):* enablePropertyFilter = true** @param filterMode 0:Tag过滤、1:SQL92过滤Tag、2:SQL92过滤自定义消息属性* @return*/@GetMapping("/sendMqByFilterMode")@ResponseBodypublic Object sendMqByFilterMode(Integer filterMode) {if (filterMode == 0) {RocketMessage message = RocketMessage.builder().name("消费过滤-Tag过滤" + LocalDateTime.now()).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.TAG_TOPIC + ":" + RocketConstant.TAG_EXPRESSION, message);return sendResult;} else if (filterMode == 1) {RocketMessage message = RocketMessage.builder().name("消费过滤-SQL92过滤Tag" + LocalDateTime.now()).build();SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.SQL92_TOPIC + ":" + RocketConstant.SQL92_TAG_EXPRESSION, message);return sendResult;} else {// Message msg = new Message("topic", "tagA", "Hello MQ".getBytes())// 设置自定义属性A,属性值为1。-> msg.putUserProperties("a", "1")//  RocketMQTemplate 目前好像不支持这种写法RocketMessage message = RocketMessage.builder().name("消费过滤-SQL92过滤自定义消息属性" + LocalDateTime.now()).build();Map<String, Object> map = new HashMap<>();map.put("a", 1);MessageHeaders messageHeaders = new MessageHeaders(map);SendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.SQL92_PROPERTIES_TOPIC, MessageBuilder.createMessage(message, messageHeaders));return sendResult;}}

4. 消息重试与死信队列:

  /*** 消息重试与死信队列* <p>* 1. 消息重试只针对集群消费模式生效;广播消费模式不提供失败重试特性,即消费失败后,* 失败消息不再重试,继续消费新的消息。* 2. 一条消息初次消费失败后,会自动进行消息重试,达到最大重试次数后,将其发送到该消费者对应的死信队列,* 这类消息称为死信消息(Dead-Letter Message)。死信队列是死信Topic下,分区数唯一的单独队列。* 3. 如果产生了死信消息,那对应的ConsumerGroup的死信Topic名称为%DLQ%ConsumerGroupName,* 死信队列的消息将不会再被消费。* 4. 可以利用RocketMQ Admin工具或者RocketMQ Dashboard上查询到对应死信消息的信息。** @return*/@GetMapping("/sendMqByRetry")@ResponseBodypublic Object sendMqByRetry() {RocketMessage message = RocketMessage.builder().name("消息重试" + LocalDateTime.now()).build();// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.RETRY_TOPIC, message);return sendResult;}

5. 消息应答:

   /*** 消息应答** @return*/@GetMapping("/sendByReply")@ResponseBodypublic Object sendByReply() {RocketMessage message = RocketMessage.builder().name("消息应答" + LocalDateTime.now()).build();RocketMessage receiveMessage = rocketMQTemplate.sendAndReceive(RocketConstant.REPLY_TOPIC, message, RocketMessage.class);return receiveMessage;}

6. Pull消费:

        Pull消费包括两种方式,主要包括:原始Pull Consumer与Lite Pull Consumer)

   /*** 原始Pull Consumer的消息发送** @return*/@GetMapping("/sendByOriginalPull")@ResponseBodypublic Object sendByOriginalPull() {List<Message> messageList = new ArrayList<>();for (int i = 0; i < 100; i++) {RocketMessage message = RocketMessage.builder().name("原始pull消息" + LocalDateTime.now() + i).build();messageList.add(MessageBuilder.withPayload(message).build());}// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.PULL_ORIGINAL_TOPIC, messageList);return sendResult;}@GetMapping("/pullByOriginal")@ResponseBodypublic void pullByOriginal() {pullMgsOriginal.pull(0, 2);}/*** 使用rocketMQTemplate拉取消息** @return*/@GetMapping("/sendByTemplatePull")@ResponseBodypublic Object sendByTemplatePull() {List<Message> messageList = new ArrayList<>();for (int i = 0; i < 100; i++) {RocketMessage message = RocketMessage.builder().name("template pull消息" + LocalDateTime.now() + i).build();messageList.add(MessageBuilder.withPayload(message).build());}// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.LITE_PULL_TEMPLATE_TOPIC, messageList);return sendResult;}/*** LitePullSubscribe** @return*/@GetMapping("/sendBySubscribePull")@ResponseBodypublic Object sendBySubscribePull() {List<Message> messageList = new ArrayList<>();for (int i = 0; i < 100; i++) {RocketMessage message = RocketMessage.builder().name("subscribe pull消息" + LocalDateTime.now() + i).build();messageList.add(MessageBuilder.withPayload(message).build());}// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.LITE_PULL_SUBSCRIBE_TOPIC, messageList);return sendResult;}@GetMapping("/pullBySubscribe")@ResponseBodypublic void pullBySubscribe() {litePullSubscribeMsg.pull(20);}/*** LitePullAssign** @return*/@GetMapping("/sendByAssignPull")@ResponseBodypublic Object sendByAssignPull() {List<Message> messageList = new ArrayList<>();for (int i = 0; i < 100; i++) {RocketMessage message = RocketMessage.builder().name("assign pull消息" + LocalDateTime.now() + i).build();messageList.add(MessageBuilder.withPayload(message).build());}// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.LITE_PULL_ASSIGN_TOPIC, messageList);return sendResult;}@GetMapping("/pullByAssign")@ResponseBodypublic void pullByAssign() {litePullAssignMsg.pull();}

7. 设置消费点位:

    /*** 消费点类型设置成:* ConsumeFromWhere.CONSUME_FROM_TIMESTAMP** @return*/@GetMapping("/sendMqByConsumePoint")@ResponseBodypublic Object sendMqByConsumePoint() {RocketMessage message = RocketMessage.builder().name("设置消费点位" + LocalDateTime.now()).build();// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.CONSUME_POINT_TOPIC, message);return sendResult;}

8. 消费者手动应答:

   /*** @param mgs 0:会抛空指针,重试三次。* @return*/@GetMapping("/sendMqByManualConfirm")@ResponseBodypublic Object sendMqByManualConfirm(Integer mgs) {RocketMessage message = RocketMessage.builder().name(mgs == null ? "消费者手动应答" + LocalDateTime.now() : String.valueOf(mgs)).build();// syncSendSendResult sendResult = rocketMQTemplate.syncSend(RocketConstant.MANUAL_CONFIRM_TOPIC, message);return sendResult;}

相关文章:

RocketMQ基础学习

前言&#xff1a; RocketMQ阿里开源的&#xff0c;一款分布式的消息中间件&#xff0c;它经过阿里的生产环境的高并发、高吞吐的考验&#xff0c;同时&#xff0c;还支持分布式事务等场景。RocketMQ使用Java语言进行开发&#xff0c;方便Java开发者学习源码。但是&#xff0c;R…...

I.MX6ULL内核开发4:设备号的组成与哈希表

目录 一、设备号 二、hash table 一、设备号 文件夹&#xff1a;/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/include/linux/kdev.h 这里面是linux中关于设备号的具体描述 #define MINORBITS 20 #define MINORMASK ((1U << MINORBITS) - 1)#defin…...

【博学谷学习记录】大数据课程-学习第六周总结

Hadoop 3.x的版本架构和模型介绍 由于Hadoop 2.0是基于JDK 1.7开发的&#xff0c;而JDK 1.7在2015年4月已停止更新&#xff0c;这直接迫使Hadoop社区基于JDK 1.8重新发布一个新的Hadoop版本&#xff0c;即hadoop 3.0。Hadoop 3.0中引入了一些重要的功能和优化&#xff0c;包括…...

Cordova

一、简介 Cordova 是用 Web 技术&#xff08; HTML&#xff0c;CSS 和 JS &#xff09;构建移动应用的平台。我们可以认为Cordova 是一个容器&#xff0c;用于将的 Web 应用移植到移动端&#xff0c;同时支持移动端的功能&#xff08;例如&#xff1a;定位、蓝牙、摄像头等&am…...

9.语义HTMLVScode扩展推荐

语义HTML 定义&#xff1a; 一个元素使用我们并不是只关心他是什么样子的&#xff0c;而是要去关心这个元素名称的实际意义或者代表什么 我们使用标签并不是他仅代表导航栏&#xff0c;只是将导航栏部分归为一个块。现实生活中&#xff0c;多使用之前都是使用div这个元素去构…...

一款非常不错的微信系统垃圾清理工具:微信清理大师,操作简单,清除较快。

微信清理大师 微信清理大师是一款专为微信所推出的系统垃圾清理工具。它的功能十分强大&#xff0c;可快捷清理微信内储存垃圾文件&#xff0c;操作十分简单&#xff0c;只需要轻轻一点&#xff0c;即可删除清理。 功能特点&#xff1a; 【一键清理】一键搞定无用垃圾&#x…...

PMP考前冲刺2.11 | 2023新征程,一举拿证

承载2023新一年的好运让我们迈向PMP终点一起冲刺&#xff01;一起拿证&#xff01;每日5道PMP习题助大家上岸PMP&#xff01;&#xff01;&#xff01;题目1-2&#xff1a;1.以下哪三种情况是Scrum主管应该注意的障碍&#xff1f;(选择三个)A. 阻碍敏捷能力的技术B. 缺乏团队授…...

yalc(比 yarn/npm link 更加友好的前端依赖库 link 方案)

参考链接: 【yalc 官方文档】:https://github.com/wclr/yalc 【yalc-watch 官方文档】:https://github.com/johot/yalc-watch 链接依赖库背景 以 D-SASS 前端框架为例,当我们在修改 D-SASS 前端框架时,当想着马上就要预览到修改的内容是否生效,于是在前端框架目录下进…...

Github | 个人资料自述文件配置的不完全总结

本文简单总结配置 Github 主页上个人资料自述文件的流程和参考文件。 更新&#xff1a;2022 / 02 / 11 Github | 配置个人主页的信息总览方法的不完全总结创建、删除个人资料自述文件编辑个人资料自述文件参考链接创建、删除个人资料自述文件 首推自然是官方说明文档 1&#…...

2022年12月电子学会Python等级考试试卷(二级)答案解析

目录 一、单选题(共25题&#xff0c;共50分) 二、判断题(共10题&#xff0c;共20分) 三、编程题(共2题&#xff0c;共30分) 青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;二级&#xff09; 一、单选题(共25题&#xff0c;共50分) 1. 运行下列程序…...

SpringCloud第二讲 Ribbon负载均衡源码分析

前言介绍&#xff1a; 这一讲我们将依据Eureka的负载均衡规则&#xff0c;Eureka的具体服务搭建以及服务注册和服务发现可以参考基于Eureka实现服务注册和服务发现_热爱Java的编程小白的博客-CSDN博客 Eureka的服务搭建之后便可以在这上面进行服务注册&#xff0c;如果存在两个…...

Clip-path实现按钮流动边框动画

前言 &#x1f44f;Clip-path实现按钮流动边框动画&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 添加div标签 <div>苏苏_icon</div>添加样式 div {position: relative;width: 220px;height: 6…...

不停服更新应用的方案:蓝绿发布、滚动发布、灰度发布

原文网址&#xff1a;不停服更新应用的方案&#xff1a;蓝绿发布、滚动发布、灰度发布_IT利刃出鞘的博客-CSDN博客 简介 本文介绍不停服更新应用的方案&#xff1a;蓝绿发布、滚动发布、灰度发布。 升级服务器的应用时&#xff0c;要停止掉老版本服务&#xff0c;将程序上传…...

有趣的KaTeX(附源码)

两年半未见&#xff0c;甚是想念 给大家带来有趣的KaTeX\KaTeXKATE​X&#xff0c;可以放在洛谷主页 文章目录1234561 1#include<bits/stdc.h>\texttt{1 \color{orange}\#include <bits/stdc.h>}1 #include <bits/stdc.h> 2usingnamespacestd;\texttt{2 \col…...

Golang map笔记

map定义三种方式package mainimport "fmt"func main() {// map 的基本定义// 第一种方式 使用make分配数据空间var map1 map[string]stringmap1 make(map[string]string, 3)map1["no1"] "北京"map1["no2"] "天津"map1[&q…...

Android Jetpack组件之WorkManager高级概念介绍与使用(三)

一、介绍 通过前面两篇&#xff0c;我们基本掌握了组件的workmanager的接入&#xff0c;以及api的使用等。但是一个框架如果运用在复杂的项目中&#xff0c;肯定需要有其他额外的支持&#xff0c;介绍来我们将会介绍高级概念&#xff0c;以及对前面的知识点进行回顾与拓展。 高…...

Spring框架中用到的设计模式(都用到了哪些设计模式?)

文章目录简单工厂模式&#xff1a;工厂模式&#xff1a;单例模式&#xff1a;原型模式&#xff1a;迭代器模式&#xff1a;代理模式&#xff1a;适配器模式&#xff1a;观察者模式&#xff1a;模板模式&#xff1a;责任链模式&#xff1a;这是一道相对有难度的题目&#xff0c;…...

Python中的类和对象(4)

1. 构造函数 &#xff08;_ init _(self[,……])&#xff09; 在类中定义 _init _() 方法&#xff0c;可以实现在实例化对象的时候进行个性化定制&#xff1a; >>> class C: ... def __init__(self, x, y): ... self.x x ... self.y y ... …...

window11 安装node及配置环境变量

一、安装环境 本教程演示的环境&#xff1a; 系统&#xff1a;win 11 64位 node.js下载地址: http://nodejs.cn/ node.js版本&#xff1a;长期支持版本&#xff08;本教程基于16.15.0&#xff09; 点击选中图标下载到电脑本地即可。 二、安装步骤 1、双击安装包&#xff0c;一…...

腾讯云服务器选购新手教程(新版流程超级详细)

腾讯云服务器购买有两个入口&#xff0c;一个是直接在秒杀活动上购买云服务器&#xff0c;价格便宜&#xff0c;2核2G4M轻量服务器&#xff0c;2核4G6M服务器、4核8G10M服务器&#xff0c;活动上购买价格便宜&#xff0c;但是服务器机型固定&#xff1b;另一个是直接在云服务器…...

Swin2SR惊艳效果展示:低清草稿图秒变4K高清作品集

Swin2SR惊艳效果展示&#xff1a;低清草稿图秒变4K高清作品集 你有没有遇到过这种情况&#xff1f;一张特别有感觉的AI生成图&#xff0c;可惜分辨率太低&#xff0c;放大后全是马赛克&#xff1b;一张珍贵的旧照片&#xff0c;像素模糊得看不清人脸&#xff1b;或者从网上找到…...

Arduino激光360°扫描库:VL53L0X+28BYJ-48低成本建图方案

1. 项目概述LaserToMap360 是一个面向嵌入式空间感知应用的轻量级 Arduino 库&#xff0c;专为构建低成本、可复现的 360 激光测距扫描系统而设计。其核心目标并非替代专业 SLAM 系统&#xff0c;而是提供一种工程上可快速验证、硬件上可即插即用、数据上可直接对接上位机可视化…...

Python异步I/O终极调优手册(含strace+py-spy+asyncio debug mode三重追踪链路图)

第一章&#xff1a;Python异步I/O性能瓶颈的本质洞察Python的async/await语法虽大幅简化了异步编程模型&#xff0c;但其底层性能瓶颈并非源于语法糖本身&#xff0c;而根植于事件循环调度机制、GIL对CPU密集型任务的制约&#xff0c;以及I/O等待与协程切换之间的隐式开销。事件…...

嵌入式Linux开发必备远程连接工具详解

1. 嵌入式Linux开发常用远程连接工具技术解析1.1 远程连接工具在嵌入式开发中的重要性嵌入式Linux开发过程中&#xff0c;开发人员经常需要远程访问目标设备进行调试、文件传输或系统监控。由于嵌入式设备通常资源有限且缺乏本地交互界面&#xff0c;远程连接工具成为开发流程中…...

Llama-3.2-3B效果体验:Ollama简单操作,产出专业级文案

Llama-3.2-3B效果体验&#xff1a;Ollama简单操作&#xff0c;产出专业级文案 1. 模型概览&#xff1a;小而精的文本生成专家 Llama-3.2-3B是Meta最新推出的轻量级语言模型&#xff0c;在3B参数规模下实现了接近大模型的文本生成质量。经过指令微调优化后&#xff0c;它在多语…...

HRNet的‘并行多分支’到底强在哪?一个动画图解带你彻底搞懂特征融合机制

HRNet并行多分支架构的视觉化解析&#xff1a;如何通过双向特征融合突破关键点检测精度瓶颈 在计算机视觉领域&#xff0c;关键点检测任务&#xff08;如人体姿态估计、人脸特征点定位&#xff09;对空间精度的要求近乎苛刻。传统卷积神经网络通过层层下采样提取语义特征的代价…...

XML Notepad:Windows平台XML文档编辑与转换的完整解决方案

XML Notepad&#xff1a;Windows平台XML文档编辑与转换的完整解决方案 【免费下载链接】XmlNotepad XML Notepad provides a simple intuitive User Interface for browsing and editing XML documents. 项目地址: https://gitcode.com/gh_mirrors/xm/XmlNotepad XML No…...

如何使用Postman,通过Mock的方式测试我们的API

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这篇文章将教会大家如何利用 postman&#xff0c;通过 Mock 的方式测试我们的 API。什么是 MockMock 是一项特殊的测试技巧&#xff0c;可以在没有依赖项的情况下进…...

二进制入门及其运算

二进制,十进制以及它们之间的转换- 十进制:我们日常生活中最常用的计数系统是\它的基数是10,使用0 - 9这十个数字来表示数。每个数位的权重是10的幂次方,从右往左依次是10⁰、10、10等。例如,数字234可以表示为210 310 410⁰。- 二进制:是计算机科学中广泛使用的计数系统。它的…...

Qwen3.5-4B-Claude-Opus部署教程:模型路径软链失效时的容错加载机制

Qwen3.5-4B-Claude-Opus部署教程&#xff1a;模型路径软链失效时的容错加载机制 1. 模型概述 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF是基于Qwen3.5-4B的推理蒸馏模型&#xff0c;特别强化了结构化分析、分步骤回答以及代码与逻辑类问题的处理能力。该版本以GG…...