ActiveMQ 高级特性:延迟消息与优先级队列实战(一)
引言
在当今的分布式系统开发中,消息中间件扮演着至关重要的角色,而 ActiveMQ 作为一款广泛使用的开源消息中间件,凭借其丰富的特性和良好的性能,深受开发者的青睐。它支持多种消息模型,如点对点和发布 / 订阅,并且具备消息持久化、事务支持等功能,能够满足不同场景下的消息通信需求。
延迟消息和优先级队列是 ActiveMQ 的两个高级特性,在实际应用中具有重要的价值。延迟消息允许消息在指定的时间后被投递,这在许多场景中都非常有用,比如订单超时处理,如果用户下单后一段时间内未支付,系统可以通过延迟消息自动取消订单;又如任务定时执行,某些任务需要在特定的时间点执行,延迟消息就能很好地实现这一需求。优先级队列则根据消息的优先级进行排序,优先处理高优先级的消息,这在任务调度系统中尤为重要,比如系统中有一些紧急任务和普通任务,通过优先级队列可以确保紧急任务优先得到处理,从而保证系统的高效运行。
本文将深入探讨 ActiveMQ 的延迟消息与优先级队列这两个高级特性,并通过实战示例详细介绍它们的使用方法和注意事项,帮助读者更好地掌握这两个特性,提升在分布式系统开发中运用 ActiveMQ 的能力。
一、ActiveMQ 基础回顾
1.1 简介
ActiveMQ 是 Apache 软件基金会所研发的开放源代码消息中间件,作为一种纯 Java 程序,只要操作系统支持 Java 虚拟机,它便可执行。它的设计目标是在尽可能多的平台和语言上提供标准的、消息驱动的应用集成 ,具备多种强大特性。
在语言支持方面,它允许使用 Java、C、C++、C#、Ruby、Perl、Python、PHP 等多种语言编写客户端,极大地拓宽了其适用范围,让不同技术栈的开发者都能轻松使用。在协议支持上,涵盖 OpenWire、Stomp REST、WS Notification、XMPP、AMQP 等,使其能适应各种复杂的网络环境和应用场景。
ActiveMQ 完全支持 JMS1.1 和 J2EE 1.4 规范,包括持久化、XA 消息、事务等功能,这使得它在企业级应用开发中表现出色,能够满足企业对于消息处理的严格要求。同时,它对 Spring 框架有着良好的支持,可以很容易地内嵌到使用 Spring 的系统里面去,并且支持 Spring2.0 的特性,方便了基于 Spring 框架的项目集成和开发 。此外,它还通过了常见 J2EE 服务器(如 Geronimo、JBoss 4、GlassFish、WebLogic)的测试,借助 JCA 1.5 resource adaptors 的配置,能够自动部署到任何兼容 J2EE 1.4 的商业服务器上 。
ActiveMQ 支持多种传送协议,如 in-VM、TCP、SSL、NIO、UDP、Jgroups、JXTA 等,为不同的应用场景提供了灵活的选择。在消息持久化方面,支持通过 JDBC 和 journal 提供高速的消息持久化,保证了消息在系统故障等情况下的可靠性。从设计架构上,它保证了高性能的集群、客户端 - 服务器、点对点等通信模式的实现,还支持 Ajax 以及与 Axis 的整合,并且可以很容易地调用内嵌 JMS provider 进行测试。
由于这些特性,ActiveMQ 被广泛应用于各种场景。在电商系统中,像京东、淘宝这类大型电商平台,在处理订单、库存、物流等模块间的通信时,ActiveMQ 可以发挥异步处理和应用解耦的作用,提高系统的响应速度和稳定性。在分布式系统开发中,它能实现不同服务之间的可靠消息传递,确保系统的各个部分能够高效协同工作。
1.2 核心组件与工作原理
- Broker:Broker 是 ActiveMQ 的核心组件,负责接收、存储和传递消息 ,可以将其看作是一个消息服务器。它可以运行在单机上,也可以分布在多个节点上组成集群,以实现高可用性和负载均衡。比如在一个大型的分布式电商系统中,可能会部署多个 Broker 节点,共同承担处理大量订单消息、库存更新消息等任务,防止单个节点因负载过高而出现性能瓶颈。
- Connection:Connection 是生产者和消费者与 Broker 之间的通信链路 ,就像是一条连接客户端(生产者或消费者)和消息服务器(Broker)的桥梁。它可以是 TCP 连接、SSL 连接或者 HTTP 连接等。当一个订单系统(生产者)要向 ActiveMQ 发送订单消息时,首先需要建立一个到 Broker 的 Connection,通过这个连接来传输消息。
- Session:Session 是生产者和消费者之间的通信会话 ,它可以是同步会话,也可以是异步会话。在 Session 中可以创建消息的生产者(MessageProducer)、消费者(MessageConsumer)以及消息的目的地(Destination,如队列 Queue 或主题 Topic)。例如,在一个物流系统(消费者)从 ActiveMQ 接收订单配送消息的过程中,会在一个 Session 内创建 MessageConsumer 来接收消息。
- Destination:Destination 是消息的接收端 ,分为队列(Queue)和主题(Topic)两种类型。队列是一种先进先出(FIFO)的数据结构,生产者将消息发送到队列,消费者从队列中按照先进先出的顺序取消息进行处理,适用于一对一的消息通信场景,比如订单系统发送订单消息到队列,库存系统从队列中获取消息更新库存。主题则采用发布 / 订阅模式,一个生产者可以向主题发送消息,多个消费者可以订阅该主题并接收到相同的消息,适用于一对多的广播通信场景,比如系统发布公告消息到主题,多个相关的业务模块都可以订阅该主题获取公告内容。
- MessageProducer:消息生产者,负责将消息发送到 Destination 。比如电商系统中的订单模块,在用户下单后,订单模块作为 MessageProducer 将订单相关消息发送到指定的 Queue 或 Topic。
- MessageConsumer:消息消费者,负责从 Destination 接收消息 。如电商系统中的物流模块,作为 MessageConsumer 从对应的 Queue 或 Topic 中接收订单消息,从而安排后续的物流配送任务。
消息的生产和消费过程如下:
- 消息生产:生产者首先创建一个 ConnectionFactory,通过它创建与 Broker 的 Connection。接着,在这个 Connection 上创建 Session。在 Session 中创建 Destination(Queue 或 Topic)以及 MessageProducer。生产者创建消息对象(如 TextMessage、ObjectMessage 等),设置好消息的内容和属性后,通过 MessageProducer 将消息发送到指定的 Destination。例如,在一个在线教育平台中,当用户购买课程后,订单系统作为生产者,创建一个包含订单信息(课程 ID、用户 ID、购买时间等)的 TextMessage,通过 MessageProducer 发送到名为 “orderQueue” 的队列中。
- 消息消费:消费者同样先创建 ConnectionFactory 和 Connection,然后在 Connection 上创建 Session,并在 Session 中创建与生产者发送消息时相同的 Destination 以及 MessageConsumer。消费者通过 MessageConsumer 接收消息,可以采用同步阻塞方式(如Message message = consumer.receive();)等待接收消息,也可以设置消息监听器(consumer.setMessageListener(new MessageListener() {... });)以异步方式接收消息。当接收到消息后,消费者对消息进行处理。比如课程管理系统作为消费者,从 “orderQueue” 队列中接收到订单消息后,解析消息内容,更新课程的销售记录等。
二、延迟消息实战
2.1 延迟消息概念与应用场景
延迟消息是指消息在发送后,并不会立即被投递到消费者,而是在经过指定的时间延迟后才被投递 。这种特性在许多实际应用场景中都非常有用。
在电商系统中,订单超时处理是一个常见的场景。当用户下单后,如果在规定的时间内(如 30 分钟)未完成支付,系统需要自动取消订单并释放库存。通过发送延迟消息,在用户下单时,向消息队列发送一条延迟 30 分钟的消息,消息内容包含订单信息。30 分钟后,消息被投递,消费者接收到消息后检查订单状态,如果订单仍未支付,则执行取消订单和释放库存的操作。
在任务定时执行场景中,比如每天凌晨需要执行数据备份任务,或者每周一需要发送周报提醒。可以在系统中设置定时任务,在合适的时间点发送延迟消息,消息到达消费者后触发相应的任务执行逻辑 。例如,在每天凌晨 0 点,系统发送一条延迟 1 分钟的消息,消费者接收到消息后启动数据备份任务,这样可以避免在整点时刻系统负载过高时执行备份任务,影响其他业务的正常运行。
在物流系统中,当货物到达目的地后,可能需要在一段时间后(如 2 小时)自动确认收货并更新物流状态。通过延迟消息,在货物到达目的地时发送一条延迟 2 小时的消息,消息包含物流单号等信息,2 小时后消息被投递,消费者根据消息内容确认收货并更新物流状态,提高物流处理的自动化程度 。
2.2 ActiveMQ 实现延迟消息的方式
2.2.1 使用 TimeToLive 属性
通过设置消息的 TimeToLive(TTL)属性可以实现延迟投递。TTL 属性表示消息在队列中的存活时间,单位为毫秒。当生产者发送消息时,设置 TTL 属性为一个大于 0 的值,消息并不会立即被投递,而是在经过 TTL 时间后才会被投递到消费者 。
例如,以下是使用 Java 代码通过设置 TimeToLive 属性实现延迟消息发送的生产者示例:
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
public class DelayedMessageProducer {
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "DelayedMessageQueue";
public static void main(String[] args) throws JMSException {
// 创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
// 创建连接
Connection connection = connectionFactory.createConnection();
// 启动连接
connection.start();
// 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建队列
Destination destination = session.createQueue(QUEUE_NAME);
// 创建消息生产者
MessageProducer producer = session.createProducer(destination);
// 创建文本消息
TextMessage message = session.createTextMessage("这是一条延迟消息");
// 设置消息的TimeToLive属性为5000毫秒,即5秒后投递
message.setJMSExpiration(System.currentTimeMillis() + 5000);
// 发送消息
producer.send(message);
System.out.println("延迟消息已发送");
// 关闭资源
producer.close();
session.close();
connection.close();
}
}
消费者代码示例如下:
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
public class DelayedMessageConsumer {
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "DelayedMessageQueue";
public static void main(String[] args) throws JMSException {
// 创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
// 创建连接
Connection connection = connectionFactory.createConnection();
// 启动连接
connection.start();
// 创建会话
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建队列
Destination destination = session.createQueue(QUEUE_NAME);
// 创建消息消费者
MessageConsumer consumer = session.createConsumer(destination);
// 接收消息,这里采用同步阻塞方式接收消息
Message message = consumer.receive();
if (message != null && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("接收到延迟消息:" + textMessage.getText());
}
// 关闭资源
consumer.close();
session.close();
connection.close();
}
}
在上述代码中,生产者创建了一条文本消息,并设置了消息的JMSExpiration属性(即 TTL)为当前时间加上 5000 毫秒,这样消息会在 5 秒后被投递。消费者通过receive方法接收消息,当消息被投递时,消费者可以接收到并处理该消息。
2.2.2 使用 Scheduled Message 机制
ActiveMQ 的 Scheduled Message 机制提供了更灵活的延迟消息设置方式 。它允许通过设置消息的属性来实现延迟投递、定时重复投递等功能。
主要涉及以下几个属性:
- AMQ_SCHEDULED_DELAY:消息延迟发送的时间,单位为毫秒 。例如,设置该属性为 60000,表示消息将在 60 秒后发送。
- AMQ_SCHEDULED_PERIOD:每次重新发送该消息的时间间隔,单位为毫秒 。如果设置了该属性,消息在延迟发送后,会按照这个时间间隔重复发送。
- AMQ_SCHEDULED_REPEAT:重新发送该消息的次数 。结合AMQ_SCHEDULED_PERIOD属性,可以实现消息的多次重复发送。
- AMQ_SCHEDULED_CRON:使用 Cron 表达式设置发送该消息的时机 。通过 Cron 表达式,可以实现更复杂的定时任务,比如每天凌晨 3 点发送消息。
要使用 Scheduled Message 机制,需要在activemq.xml配置文件中开启 schedulerSupport属性,即在broker节点上添加schedulerSupport="true",如下所示:
<broker xmlns="http://activemq.apache.org/schema/core" schedulerSupport="true">
<!-- 其他配置 -->
</broker>
以下是基于 Spring Boot 的代码示例,展示如何使用 Scheduled Message 机制发送延迟消息:
首先,在pom.xml文件中添加 ActiveMQ 和 Spring JMS 的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jms</artifactId>
</dependency>
</dependencies>
然后,在application.yml文件中配置 ActiveMQ 的连接信息:
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
接着,创建消息发送服务类:
import org.apache.activemq.ScheduledMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
@Service
public class ScheduledMessageService {
@Autowired
private JmsTemplate jmsTemplate;
public void sendScheduledMessage(String destinationName, String messageContent, long delay, long period, int repeat) {
jmsTemplate.send(destinationName, session -> {
// 创建文本消息
javax.jms.TextMessage textMessage = session.createTextMessage(messageContent);
// 设置延迟发送时间
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
// 设置重复发送时间间隔
if (period > 0) {
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, period);
}
// 设置重复发送次数
if (repeat > 0) {
textMessage.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, repeat);
}
return textMessage;
});
}
}
最后,在测试类中调用发送方法:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ScheduledMessageTest {
@Autowired
private ScheduledMessageService scheduledMessageService;
@Test
public void testSendScheduledMessage() {
// 发送延迟消息,延迟60秒发送,不重复发送
scheduledMessageService.sendScheduledMessage("ScheduledMessageQueue", "这是一条定时延迟消息", 60000, 0, 0);
}
}
在上述代码中,通过ScheduledMessageService类的sendScheduledMessage方法发送延迟消息,设置了消息的延迟时间为 60 秒,不设置重复发送时间间隔和次数。在测试类中调用该方法,即可发送延迟消息 。消费者的代码与前面使用 TimeToLive 属性时的消费者代码类似,通过监听队列接收消息并处理。
2.3 实战案例与代码实现
2.3.1 案例背景与需求分析
假设我们正在开发一个电商系统,其中订单模块需要实现订单支付超时取消的功能。当用户下单后,系统生成订单并发送到消息队列,同时设置订单的支付超时时间为 30 分钟。如果在 30 分钟内用户未完成支付,系统需要自动取消订单,并将订单状态更新为 “已取消”,同时释放订单中占用的库存 。
为了实现这个功能,我们可以利用 ActiveMQ 的延迟消息特性。在用户下单时,向 ActiveMQ 发送一条包含订单信息的延迟消息,延迟时间设置为 30 分钟。30 分钟后,消息被投递到消费者,消费者接收到消息后检查订单的支付状态,如果订单未支付,则执行取消订单和释放库存的操作 。
2.3.2 代码实现与配置
首先,创建一个 Spring Boot 项目,并在pom.xml文件中添加 ActiveMQ 和 Spring JMS 的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jms</artifactId>
</dependency>
</dependencies>
然后,在application.yml文件中配置 ActiveMQ 的连接信息:
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
接下来,创建订单实体类Order:
import java.io.Serializable;
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
private Long orderId;
private String orderNo;
private String status;
// 其他订单相关属性和getter、setter方法
}
创建消息发送服务类OrderMessageSender:
import org.apache.activemq.ScheduledMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
@Service
public class OrderMessageSender {
@Autowired
private JmsTemplate jmsTemplate;
public void sendOrderMessage(Order order, long delay) {
jmsTemplate.send("OrderQueue", session -> {
// 创建对象消息,因为要传递订单对象
javax.jms.ObjectMessage objectMessage = session.createObjectMessage(order);
// 设置延迟发送时间,单位毫秒
objectMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
return objectMessage;
});
}
}
创建消息接收服务类OrderMessageReceiver:
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;
@Service
public class OrderMessageReceiver {
@JmsListener(destination = "OrderQueue")
public void receiveOrderMessage(Order order) {
// 检查订单支付状态,这里假设订单实体中有支付状态字段,实际应用中需要从数据库查询
if ("未支付".equals(order.getStatus())) {
// 执行取消订单操作,更新订单状态到数据库
order.setStatus("已取消");
// 模拟释放库存操作
System.out.println("订单 " + order.getOrderNo() + " 支付超时,已取消,库存已释放");
} else {
System.out.println("订单 " + order.getOrderNo() + " 已支付,无需取消");
}
}
}
在ActiveMQ的配置文件activemq.xml中,确保开启了 schedulerSupport属性:
<broker xmlns="http://activemq.apache.org/schema/core" schedulerSupport="true">
<!-- 其他配置 -->
</broker>
在订单创建的业务逻辑中,调用消息发送服务发送延迟消息:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderMessageSender orderMessageSender;
@PostMapping("/orders")
public String createOrder(@RequestBody Order order) {
// 模拟订单创建,设置订单编号和初始状态
order.setOrderNo("20240101001");
order.setStatus("未支付");
// 发送延迟消息,延迟30分钟,单位毫秒
orderMessageSender.sendOrderMessage(order, 30 * 60 * 1000);
return "订单已创建,等待支付";
}
}
2.3.3 测试与验证
启动 ActiveMQ 服务和 Spring Boot 应用。使用 Postman 等工具向/orders接口发送 POST 请求,请求体中包含订单信息,模拟用户下单操作 。
发送请求后,查看控制台输出,确认订单消息已发送。等待 30 分钟后,再次查看控制台输出,应该能看到订单支付超时取消的相关信息,如 “订单 20240101001 支付超时,已取消,库存已释放” 。
为了更准确地验证,可以在数据库中查看订单状态是否已更新为 “已取消”,以及库存相关数据是否已恢复到订单创建前的状态 。通过以上测试,可以验证延迟消息是否按照预期时间投递和消费,以及订单支付超时取消功能是否正常工作。
相关文章:
ActiveMQ 高级特性:延迟消息与优先级队列实战(一)
引言 在当今的分布式系统开发中,消息中间件扮演着至关重要的角色,而 ActiveMQ 作为一款广泛使用的开源消息中间件,凭借其丰富的特性和良好的性能,深受开发者的青睐。它支持多种消息模型,如点对点和发布 / 订阅&#x…...
动手学深度学习12.4.硬件-笔记练习(PyTorch)
以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。 本节课程地址:31 深度学习硬件:CPU 和 GPU【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&am…...
LAN-402 全国产信号采集处理模块K7-325T(4通道采集)
UD LAN-402全国产化信号处理模块最多支持2通道16bit125Msps的短波采集(或2通道14bit250Msps超短波采集)、2通道16bit310Msps超短波采集,可选配XC7K325T、XC7K410T、JFM7K325T、JFM7K410T FPGA芯片,对外支持PCIe2.0x8接口、千兆网、…...
关于大语言模型的困惑度(PPL)指标优势与劣势
1. 指标本身的局限性 与人类感知脱节: PPL衡量的是模型对词序列的预测概率(基于交叉熵损失),但低困惑度未必对应高质量的生成结果。例如: 模型可能生成语法正确但内容空洞的文本(PPL低但质量差)…...
[Spring AOP 8] Spring AOP 源码全流程总结
Spring AOP总结 更美观清晰的版本在:Github 前面的章节: [Spring AOP 1] 从零开始的JDK动态代理 [Spring AOP 2] 从零开始的CGLIB动态代理 [Spring AOP 3] Spring选择代理 [Spring AOP 4] Spring AOP 切点匹配 [Spring AOP 5] 高级切面与低级切面&#…...
通信网络编程——JAVA
1.计算机网络 IP 定义与作用 :IP 地址是在网络中用于标识设备的数字标签,它允许网络中的设备之间相互定位和通信。每一个设备在特定网络环境下都有一个唯一的 IP 地址,以此来确定其在网络中的位置。 分类 :常见的 IP 地址分为 I…...
支持向量机算法
支持向量机(Support Vector Machine,SVM)作为机器学习领域中一颗耀眼的明星,凭借其卓越的分类与回归能力,在众多算法中独树一帜。它宛如一位精准的边界守护者,通过巧妙地构建超平面,将不同类别的…...
Redis集群模式、持久化、过期策略、淘汰策略、缓存穿透雪崩击穿问题
Redis四种模式 单节点模式 架构:单个Redis实例运行在单台服务器。 优点: 简单:部署和配置容易,适合开发和测试。 低延迟:无网络通信开销。 缺点: 单点故障&…...
【WPF】Opacity 属性的使用
在WPF(Windows Presentation Foundation)中,Opacity 属性是定义一个元素透明度的属性,其值范围是从 0.0(完全透明)到 1.0(完全不透明)。由于 Opacity 是在 UIElement 类中定义的&…...
编程题 02-线性结构3 Reversing Linked List【PAT】
文章目录 题目输入格式输出格式输入样例输出样例 题解解题思路完整代码 编程练习题目集目录 题目 Given a constant K K K and a singly linked list L L L, you are supposed to reverse the links of every K K K elements on L L L. For example, given L being 1 → …...
集成指南:如何采用融云 Flutter IMKit 实现双端丝滑社交体验
在移动应用开发领域,跨平台框架的广泛应用已成为一种趋势。 融云跨平台方案持续升级,近期正式上线 Flutter IMKit,uni-app IMKit 也将紧随其后向广大开发者开放。覆盖两大跨平台核心框架,一套代码即可支持 Android、iOS 双端丝滑…...
使用vite重构vue-cli的vue3项目
一、修改依赖 首先修改 package.json,修改启动方式与相应依赖 移除vue-cli并下载vite相关依赖,注意一些peerDependency如fast-glob需要手动下载 # 移除 vue-cli 相关依赖 npm remove vue/cli-plugin-babel vue/cli-plugin-eslint vue/cli-plugin-rout…...
LeetCode 2094.找出 3 位偶数:遍历3位偶数
【LetMeFly】2094.找出 3 位偶数:遍历3位偶数 力扣题目链接:https://leetcode.cn/problems/finding-3-digit-even-numbers/ 给你一个整数数组 digits ,其中每个元素是一个数字(0 - 9)。数组中可能存在重复元素。 你…...
FLASH闪存(擦除、编译)
FLASH闪存 文章目录 FLASH闪存1.存储器映像位置2.FLASH简介3.闪存模块组织3.2闪存的共性: 4.FLASH基本结构4.1FLASH解锁4.2使用指针访问寄存器 5.选项字节5.1选项字节编程5.2选项字节擦除 6.相关函数介绍7.读取内部FLASH(实操)7.1接线图7.2工…...
企业即时通讯软件,私有化安全防泄密
在数字化转型与信创战略双重驱动下,企业对即时通讯工具的需求已从基础沟通转向安全可控、高效协同的综合能力。BeeWorks作为一款专为政企设计的私有化即时通讯与协同办公平台,凭借其全链路安全架构、深度国产化适配及灵活的业务集成能力,成为…...
直方图特征结合 ** 支持向量机图片分类
一、核心技术框架 1. 直方图特征原理 颜色直方图:统计图像中每个颜色区间(如 RGB 通道)的像素数量,反映颜色分布。HOG 直方图(方向梯度直方图):统计图像局部区域的梯度方向分布,捕…...
【prometheus+Grafana篇】基于Prometheus+Grafana实现windows操作系统的监控与可视化
💫《博主主页》: 🔎 CSDN主页 🔎 IF Club社区主页 🔥《擅长领域》:擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(MongoDB)有了…...
PyTorch实战(4)——卷积神经网络(Convolutional Neural Network, CNN)详解
PyTorch实战(4)——卷积神经网络详解 0. 前言1. 全连接网络的缺陷2. 卷积神经网络基本组件2.1 卷积2.2 步幅和填充2.3 池化2.3 卷积神经网络完整流程 3. 卷积和池化相比全连接网络的优势4. 使用 PyTorch 构建卷积神经网络4.1 使用 PyTorch 构建 CNN 架构…...
【Python】Python常用控制结构详解:条件判断、遍历与循环控制
Python提供了多种控制结构来处理逻辑判断和循环操作,包括if-else条件分支、switch替代方案、遍历方法以及循环控制语句break和continue。以下是对这些功能的详细说明及示例: 一、条件判断:if-else与多分支结构 单分支结构 • 语法࿱…...
在Linux中安装JDK并且搭建Java环境
1.首先准备好JDK的Linux的安装包 2.打开Linux,进入root的文件夹,直接拖入即可 3.输入解压命令,后面指定的是位置(注意不要填写错误,就填写这个) 4.之后进入我们安装的jdk的文件 利用pwd命令,展示我们安装的目录,之后…...
理解多智能体深度确定性策略梯度MADDPG算法:基于python从零实现
引言:多智能体强化学习(MARL) 多智能体强化学习(MARL)将强化学习拓展到多个智能体在共享环境中相互交互的场景。这些智能体可能相互合作、竞争,或者目标混杂。MARL 引入了单智能体设置中不存在的独特挑战。…...
【AI大语言模型本质分析框架】
AI大语言模型本质分析框架 ——从教育危机到智能本质的七层递进式解构 第一层:现象观察——阴(显性危机)与阳(隐性变革)的共存 观点1(阴):AI作弊泛滥,传统教育体系崩溃…...
算法模型部署后_python脚本API测试指南-记录3
API 测试指南 服务运行后,可以通过以下方式测试: Curl: curl -X POST -F "file./test_dataset/surface/surface57.png" http://<服务器IP>:9000/api/v1/predictPython 脚本: (参考 svm_request测试.py) import requestsurl http://…...
鸿蒙(HarmonyOS)应用开发入门教程
目录 第一章:鸿蒙系统简介 1.1 什么是鸿蒙系统? 1.2 鸿蒙系统架构 第二章:开发环境搭建 2.1 安装DevEco Studio 步骤1:下载与安装 步骤2:首次配置 步骤3:设备准备 2.2 创建第一个项目 第三章:鸿蒙应用开发基础 3.1 核心概念:Ability与AbilitySlice 示例代码…...
MIT XV6 - 1.6 Lab: Xv6 and Unix utilities -uptime
接上文 MIT XV6 - 1.5 Lab: Xv6 and Unix utilities - xargs 第一章持续有点久了,虽然肯定有些特点和细节还没注意到,但这次的主要目的是学习内核部分,决定水一篇然后进入第二章节 uptime 第一章的最后一个实验,选做性质…...
Python语言在地球科学交叉领域中的应用——从数据可视化到常见数据分析方法的使用【实例操作】
前言: Python是功能强大、免费、开源,实现面向对象的编程语言,Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台(x86和arm),Python简洁的语法和对动态输入的支持,再加上解释…...
flutter 的 json序列化和反序列化
一、json转实体 Instantly parse JSON in any language | quicktype 二、实体中的toJson和fromJson 实现 官方推荐的 两个插件(个人觉得一个实体会多一个.g.dart 文件太多了,不喜欢) json_annotation json_serializable 三、使用 dart_json_mapper 实现上面的功…...
什么是数据集市(Data Mart)?
数据集市(Data Mart)是数据仓库(Data Warehouse)的一个子集,专门针对某个特定业务部门、业务线或主题领域,存储和管理该部门或领域所需的特定数据。它通常包含从企业范围的数据仓库中抽取、筛选和汇总的部分…...
从攻击者角度来看Go1.24的路径遍历攻击防御
目录 一、具体攻击示例 程序 攻击步骤: 二、为什么攻击者能成功? 分析 类比理解 总结 三、TOCTOU 竞态条件漏洞 1、背景:符号链接遍历攻击 2. TOCTOU 竞态条件漏洞 3. 另一种变体:目录移动攻击 4. 问题的核心 四、防…...
[ARM][汇编] 01.基础概念
目录 1.全局标号 1.1.使用方法 1.1.1.声明全局标号 1.1.2.定义全局标号 1.1.3.引用全局标号 1.2.全局标号与局部标号的区别 1.3.注意事项 2.局部标号 2.1.使用方法 2.1.1.定义局部标号 2.1.2.跳转引用 2.2.局部标号与全局标号的对比 2.3.注意事项 3.符号定义伪指…...
杭州电商全平台代运营领军者——品融电商
杭州电商全平台代运营领军者——品融电商:以“效品合一”驱动品牌全域增长 在电商行业竞争日益白热化的当下,品牌如何突破流量焦虑、实现长效增长?作为中国领先的品牌化电商服务商,杭州品融电商(PINKROON)…...
02.Golang 切片(slice)源码分析(一、定义与基础操作实现)
Golang 切片(slice)源码分析(一、定义与基础操作实现) 注意当前go版本代码为1.23 一、定义 slice 的底层数据是数组,slice 是对数组的封装,它描述一个数组的片段。两者都可以通过下标来访问单个元素。 数…...
当生产了~/qt-arm/bin/qmake,可以单独编译其他-源码的某个模块,如下,编译/qtmultimedia
cd ~/qt-everywhere-src-5.15.2/qtmultimedia # 设置交叉编译器和 qmake 路径 export CC/usr/bin/aarch64-linux-gnu-gcc export CXX/usr/bin/aarch64-linux-gnu-g export QMAKE~/qt-arm/bin/qmake # 使用已安装的 qmake export QT_INSTALL_PREFIX~/qt-arm # 安装路径 # 配…...
WordPress 网站上的 jpg、png 和 WebP 图片插件
核心功能 1. 转换 AVIF 并压缩 AVIF 将您 WordPress 网站上的 jpg、png 和 WebP 图片转换为 AVIF 格式,并根据您设置的压缩级别压缩 AVIF 图片。如果原始图片已经是 WordPress 6.5 以上支持的 AVIF 格式,则原始 AVIF 图片将仅被压缩。 2. 转换 WebP 并…...
构造+简单树状
昨日的牛客周赛算是比较简单的,其中最后一道构造题目属实眼前一亮。 倒数第二个题目也是一个很好的模拟题目(考验对二叉树的理解和代码的细节) 给定每一层的节点个数,自己拟定一个父亲节点,构造一个满足条件的二叉树。…...
Flask支持哪些日志框架
目录 ✅ Flask 默认支持的日志框架 ✅ 默认推荐:logging(标准库) ✅ 进阶推荐:Loguru(更优雅的日志库) ✅ Flask 日志级别说明(与标准库一致) ✅ 生产环境建议 ✅ 总结推荐 在 Flask 中,默认的日志系统是基于 Python 标准库 logging 模块 构建的。 ✅ Flask 默认…...
健康养生指南:解锁活力生活的科学密码
健康是人生最珍贵的财富,在快节奏的现代生活中,掌握科学的养生方法至关重要。虽然不借助中医理念,我们依然可以从饮食、运动、睡眠等多个方面入手,打造健康生活方式。 合理的饮食是健康的基石。遵循均衡饮食原则,保证每…...
SAR图像压缩感知
SAR图像压缩感知 matlab代码 对应着汕大闫老师的那本压缩感知及其应用,有需要的可以看一下!! SAR图像压缩感知/baboon.bmp , 66616 SAR图像压缩感知/camera.bmp , 66616 SAR图像压缩感知/DWT.m , 1265 SAR图像压缩感知/Gauss.m , 373 SAR图像…...
定时器设计
定时器设计的必要性 服务器中的定时器设计具有多方面的必要性,主要体现在以下几个关键方面: 任务调度与管理 定时任务执行:服务器常常需要执行一些定时性的任务,如定时备份数据、定时清理缓存、定时更新系统日志等。通过定时器可…...
Spring Boot整合Kafka实战指南:从环境搭建到消息处理全解析
一、环境准备 安装 Kafka 下载 Kafka:从 Apache Kafka 官网下载对应版本的 Kafka。 解压并启动 Kafka: # 启动 Zookeeper(Kafka 依赖 Zookeeper) bin/zookeeper-server-start.sh config/zookeeper.properties# 启动 Kafka bin/ka…...
(done) 补充:xv6 的一个用户程序 init 是怎么启动的 ?它如何启动第一个 bash ?
先看 main.c 从函数名来看,比较相关的就 userinit() 和 scheduler() #include "types.h" #include "param.h" #include "memlayout.h" #include "riscv.h" #include "defs.h"volatile static int started 0;//…...
AI 搜索引擎 MindSearch
背景 RAG是一种利用文档减少大模型的幻觉,AI搜索也是 AI 搜索引擎 MindSearch 是一个开源的 AI 搜索引擎框架,具有与 Perplexity.ai Pro 相同的性能。您可以轻松部署它来构建您自己的搜索引擎,可以使用闭源 LLM(如 GPT、Claude…...
HTML简单语法标签(后续实操:云备份项目)
以下是一些 HTML 的简单语法标签及其功能介绍: 基本结构标签 <!DOCTYPE html>:声明文档类型为 HTML5<html>:HTML 文档的根标签<head>:包含文档元数据(如标题、字符编码等)<title>…...
CentOS 和 RHEL
CentOS 和 RHEL(Red Hat Enterprise Linux)关系非常紧密,简而言之: CentOS 最初是 RHEL 的免费、开源克隆版,几乎与 RHEL 二进制兼容。 CentOS 原是 RHEL 的“免费双胞胎”,但已被放弃,现在推荐…...
java----------->代理模式
目录 什么是代理模式? 为什么会有代理模式? 怎么写代理模式? 实现代理模式总共需要三步: 什么是代理模式? 代理模式:给目标对象提供一个代理对象,并且由代理对象控制目标对象的引用 代理就是…...
Wpf学习片段
IRegionManager 和IContainerExtension IRegionManager 是 Prism 框架中用于管理 UI 区域(Regions)的核心接口,它实现了模块化应用中视图(Views)的动态加载、导航和生命周期管理。 IContainerExtension 是依赖注入&…...
智能手表测试用例文档
智能手表测试用例文档 产品名称:智能手表 A1 版本号:FW v1.0.0 测试负责人:[填写] 编写时间:2025-xx-xx 文档状态:初次版本 📁 测试用例结构说明 字段描述用例编号测试用例唯一编号,如 TC-FUN…...
密码学--希尔密码
一、实验目的 1、通过实现简单的古典密码算法,理解密码学的相关概念 2、理解明文、密文、加密密钥、解密密钥、加密算法、解密算法、流密码与分组密码等。 二、实验内容 1、题目内容描述 ①定义分组字符长度 ②随机生成加密密钥,并验证密钥的可行性 …...
配置Hadoop集群-集群配置
以下是 Hadoop 集群的核心配置步骤,基于之前的免密登录和文件同步基础,完成 Hadoop 分布式环境的搭建: 1. 集群规划 假设集群包含 3 个节点: master:NameNode、ResourceManagerslave1:DataNode、NodeMana…...
第三方软件测评中心分享:软件功能测试类型和测试工具
在数字化时代,软件测试已成为确保产品质量的重要环节。功能测试作为软件测试中的核心部分,关注于软件产品是否按预期功能正常运作。 软件功能测试可以按不同的方式进行分类,主要包括以下几种类型: 1.正功能测试:验…...