微服务架构 --- 使用RabbitMQ进行异步处理

目录

一.什么是RabbitMQ?

二.异步调用处理逻辑:

三.RabbitMQ的基本使用:

1.安装:

2.架构图:

 3.RabbitMQ控制台的使用:

(1)Exchanges 交换机:

(2)Queues 队列:

 (3)Admin :

①Users(用户管理):

②Virtual Hosts(虚拟主机):

 四.SpringAMOP的使用:

1.导入依赖:

2.添加配置:

3.在publisher服务中利用RabbitTemplate实现消息发送:

4.定义消费者实现异步调用:

①@RequiredArgsConstructor:

②@RabbitListener:

③QueueBinding(队列绑定):

5.总流程处理过程:

五.使用配置类管理定义交换机,队列及两者关系:

1.创建队列:Queue:

2.创建交换机:Exchange:

 3.创建绑定关系:Binding:

 4.多个队列绑定到同一个交换机:

5.配置不同类型的交换机:

(1)Direct Exchange:

(2)Fanout Exchange:

(3)Headers Exchange:

总结:


一.什么是RabbitMQ?

RabbitMQ 是一种流行的消息队列(Message Queue)实现,基于 AMQP 协议(Advanced Message Queuing Protocol)。它支持异步通信,使多个系统之间以非阻塞的方式交换数据。

在我们使用微服务的时候,微服务一旦拆分,必然涉及到服务之间的相互调用,目前我们服务之间调用采用的都是基于 OpenFeign 的调用。这种调用中,调用者发起请求后需要等待服务提供者执行业务返回结果后,才能继续执行后面的业务。也就是说调用者在调用过程中处于阻塞状态,因此我们称这种调用方式为同步调用,也可以叫同步通

如果我们的业务需要实时得到服务提供方的响应,则应该选择同步通讯(同步调用)。而如果我们追求更高的效率,并且不需要实时响应,则应该选择异步通讯(异步调用)。

二.异步调用处理逻辑:

异步调用方式其实就是基于消息通知的方式,一般包含三个角色:

  • 消息发送者:投递消息的人,就是原来的调用方

  • 消息Broker:管理、暂存、转发消息,你可以把它理解成微信服务器

  • 消息接收者:接收和处理消息的人,就是原来的服务提供方

 在异步调用中,发送者不再直接同步调用接收者的业务接口,而是发送一条消息投递给消息Broker。然后接收者根据自己的需求从消息Broker那里订阅消息。每当发送方发送消息后,接受者都能获取消息并处理。这样,发送消息的人和接收消息的人就完全解耦了。

异步调用的优势包括:

  • 耦合度更低

  • 性能更好

  • 业务拓展性强

  • 故障隔离,避免级联失败

当然,异步通信也并非完美无缺,它存在下列缺点:

  • 完全依赖于Broker的可靠性、安全性和性能

  • 架构复杂,后期维护和调试麻烦

三.RabbitMQ的基本使用:

下面是RabbitMQ的官网:https://www.rabbitmq.com/

1.安装:

首先将RabbitMQ的镜像拉取下来,然后运行下面命令:

docker run \
 -e RABBITMQ_DEFAULT_USER=itheima \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 --hostname mq \
 -p 15672:15672 \
 -p 5672:5672 \
 --network hm-net\
 -d \
 rabbitmq:3.8-management

随后我们访问http://虚拟机IP地址:15672来打开RabbitMQ的控制台。

在控制台上主要可以关注三个信息:Exchanges(交换机),Queues(队列),Admin(用户管理)。

2.架构图:

 

其中包含几个概念:

  • publisher:生产者,也就是发送消息的一方

  • consumer:消费者,也就是消费消息的一方

  • queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理

  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。

  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue

 3.RabbitMQ控制台的使用:

RabbitMQ 中,交换机(Exchange)队列(Queue) 是核心概念。它们之间的关系决定了消息的路由和存储方式。

(1)Exchanges 交换机:

  • 交换机是 消息的路由器,负责决定消息应该被发送到哪个队列。
  • 生产者将消息发送给交换机,而不是直接发送到队列。
  • 交换机根据路由规则 决定消息的走向(即发往哪些队列)。

Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

RabbitMQ 提供了四种常用的交换机类型,每种类型的路由规则不同:

  • Fanout:广播,将消息交给所有绑定到交换机的队列。我们最早在控制台使用的正是Fanout交换机

  • Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列

  • Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符

  • Headers:头匹配,基于MQ的消息头匹配,用的较少。

我们可以再这里创建交换机,Name表示创建的交换机的名字,Type表示可以选择交换机的四种类型。创建成功后就可以在上面看到创建的交换机名字:

比如我们点击amq.fanout查看交换机数据并且可以发送消息给消费者。

注意!!!如果我们不将交换机指定队列的话,由于没有消费者存在,最终消息丢失了,这样说明交换机没有存储消息的能力。

 所以下面我们要先创建队列,然后让生产者推送的消息经过交换机的传递后,到达消息队列,然后再给消费者。所以生产者无需知道队列的存在以此来达到解耦的效果

(2)Queues 队列:

  • 队列用于 存储消息,直到消费者消费它们。
  • 队列与消费者一一对应,即一个消费者从一个队列读取消息。
  • 队列按 FIFO(First In, First Out)的顺序存储消息。

在这里我们填写队列名字即可,其他暂时可以不用填写。 

随后我们向交换机进行绑定(bind)队列,随后通过队列传输给消费者。

这里的Routing key的出现是为了让 Direct (交换机的类型)能够选择队列而存在的。

我们在绑定队列完成后会出现下面这样,这样证明我们成功为交换机绑定好两个队列:

随后我们在下面窗口推送消息:

 (3)Admin :

①Users(用户管理):

管理 RabbitMQ 中的用户账号,在这里 添加、删除用户,并设置每个用户的权限。

每个用户可分配不同的 角色

  • administrator:管理员,具有所有权限。
  • monitoring:可以监控和查看信息,但不能管理。
  • policymaker:可以设置策略和参数。
  • management:可以访问管理界面但没有策略权限。

  • Nameitheima,也就是用户名

  • Tagsadministrator,说明itheima用户是超级管理员,拥有所有权限

  • Can access virtual host/,可以访问的virtual host,这里的/是默认的virtual host

②Virtual Hosts(虚拟主机):

将 RabbitMQ 服务器划分为多个 虚拟主机(vhost),类似于一个独立的命名空间。

  • 不同的应用可以使用不同的虚拟主机,彼此隔离。
  • 每个虚拟主机都有自己的 交换机、队列和用户权限

 四.SpringAMOP的使用:

Spring AMQPSpring for Advanced Message Queuing Protocol)是 Spring 提供的一个消息队列集成模块,主要用于简化与 RabbitMQ 的集成。它通过 AMQP 协议来实现消息的生产和消费。

  • Publisher:生产者,不再发送消息到队列中,而是发给交换机

  • Exchange:交换机,一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。

  • Queue:消息队列也与以前一样,接收消息、缓存消息。不过队列一定要与交换机绑定。

  • Consumer:消费者,与以前一样,订阅队列,没有变化

1.导入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.添加配置:

publisher以及consumer服务的application.yml中添加配置:

spring:
  rabbitmq:
    host: 192.168.150.101 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: /hmall # 虚拟主机
    username: hmall # 用户名
    password: 123 # 密码
    listener:
      simple:
        prefetch: 1 # (能者多劳)每次只能获取一条消息,处理完成才能获取下一个消息

3.在publisher服务中利用RabbitTemplate实现消息发送:

@SpringBootTest
public class SpringAmqpTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSimpleQueue() {
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, spring amqp!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }
}

4.定义消费者实现异步调用:

@Component
@RequiredArgsConstructor
public class PayStatusListener {

    private final IOrderService orderService;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "trade.pay.success.queue", durable = "true"),
            exchange = @Exchange(name = "pay.topic"),
            key = "pay.success"
    ))
    public void listenPaySuccess(Long orderId){
        //调用方法
        orderService.markOrderPaySuccess(orderId);
    }
}

①@RequiredArgsConstructor:

这是 Lombok 提供的注解,自动为类中所有 final 修饰的字段生成一个包含这些字段的构造函数。使用这个注解可以免去手动编写构造函数的麻烦,尤其是在使用依赖注入时(例如注入 IOrderService)。

②@RabbitListener:

@RabbitListener 注解用于监听来自 RabbitMQ 队列的消息。它会自动监听指定的队列,当有消息到达时,会触发 listenPaySuccess 方法进行处理。

③QueueBinding(队列绑定):

通过 @QueueBinding 注解,绑定了 队列交换机,并指定了 路由键

  • @Queue
    • name = "trade.pay.success.queue":指定队列的名称为 trade.pay.success.queue
    • durable = "true":表示队列是 持久化 的,即 RabbitMQ 重启后队列依然存在。
    • 队列的作用:队列是消息的临时存储地,消费者会从队列中拉取消息并处理。
  • @Exchange
    • name = "pay.topic":指定交换机的名称为 pay.topic,这是一个 Topic Exchange(主题交换机)。
    • 交换机的作用:交换机决定消息如何路由到队列。Topic Exchange 可以根据路由键的匹配规则将消息路由到合适的队列。
  • key = "pay.success"
    • 路由键:指定了路由键为 pay.success。这意味着当生产者发送的消息路由键是 pay.success 时,消息将被路由到 trade.pay.success.queue 队列。

5.总流程处理过程:

  • 生产者:在支付成功后,生产者会发送一条消息到 pay.topic 交换机,消息的路由键为 pay.success
  • 交换机pay.topic 交换机会根据路由键 pay.success 将消息路由到 trade.pay.success.queue 队列。
  • 消费者PayStatusListener 作为消费者监听 trade.pay.success.queue,当有消息到达队列时,它会接收到订单 ID 并调用订单服务更新订单状态。

五.使用配置类管理定义交换机,队列及两者关系:

在 Spring AMQP 中,交换机(Exchange)、队列(Queue)、以及绑定(Binding)可以通过配置类来定义和管理。配置类可以帮助你灵活地创建和绑定交换机与队列,并且可以根据业务需求自定义各种参数。

创建配置类效果展示:

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    // 创建队列
    @Bean
    public Queue queue() {
        return new Queue("trade.pay.success.queue", true); // durable=true 表示队列持久化
    }

    // 创建交换机
    @Bean
    public TopicExchange exchange() {
        return new TopicExchange("pay.topic"); // 创建主题交换机
    }

    // 创建绑定关系(队列与交换机通过 routing key 绑定)
    @Bean
    public Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("pay.success"); // 路由键是 pay.success
    }
}

1.创建队列:Queue:

@Bean
public Queue queue() {
    return new Queue("trade.pay.success.queue", true);
}
  • 作用:通过 @Bean 注解定义了一个队列 Bean。Spring 容器会自动管理这个队列,并在 RabbitMQ 上创建该队列。
  • 参数
    • "trade.pay.success.queue":这是队列的名称。每个队列在 RabbitMQ 中必须有唯一的名称。
    • true:表示这个队列是 持久化 的。持久化的队列在 RabbitMQ 服务重启后依然存在。

2.创建交换机:Exchange:

@Bean
public TopicExchange exchange() {
    return new TopicExchange("pay.topic");
}
  • 作用:通过 @Bean 注解定义了一个 Topic Exchange 类型的交换机。
  • 参数
    • "pay.topic":这是交换机的名称。同样,交换机在 RabbitMQ 中也必须有唯一的名称。

Topic Exchange 是一种交换机类型,它允许使用通配符来进行路由。例如,路由键可以是 "pay.*",可以匹配 "pay.success""pay.failure"。在这里可以使用四种交换机类型来定义交换机,具体场景具体分析使用。

 3.创建绑定关系:Binding:

@Bean
public Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with("pay.success");
}
  • 作用:通过 @Bean 注解定义了队列和交换机的绑定关系。这个绑定决定了消息在何种条件下会从交换机路由到队列。
  • 参数
    • queue:我们定义的 trade.pay.success.queue 队列。
    • exchange:我们定义的 pay.topic 交换机。
    • "pay.success":这是路由键(Routing Key)。它用于告诉交换机:只有当消息的路由键是 pay.success 时,消息才会被路由到 trade.pay.success.queue 队列。

 4.多个队列绑定到同一个交换机:

我们可以将多个队列绑定到同一个交换机,并使用不同的路由键。这样可以实现根据不同的路由键来发送不同类型的消息到各自的队列。

@Bean
public Queue paySuccessQueue() {
    return new Queue("pay.success.queue", true);
}

@Bean
public Queue payFailureQueue() {
    return new Queue("pay.failure.queue", true);
}

@Bean
public Binding paySuccessBinding(Queue paySuccessQueue, TopicExchange exchange) {
    return BindingBuilder.bind(paySuccessQueue).to(exchange).with("pay.success");
}

@Bean
public Binding payFailureBinding(Queue payFailureQueue, TopicExchange exchange) {
    return BindingBuilder.bind(payFailureQueue).to(exchange).with("pay.failure");
}
  • 在这个例子中,pay.success.queuepay.failure.queue 都绑定到同一个交换机 pay.topic,但使用不同的路由键。
  • 消息路由逻辑
    • 当生产者发送路由键为 pay.success 的消息时,消息会路由到 pay.success.queue 队列。
    • 当生产者发送路由键为 pay.failure 的消息时,消息会路由到 pay.failure.queue 队列。

5.配置不同类型的交换机:

除了 Topic Exchange,RabbitMQ 还支持其他几种常见的交换机类型。这里分别演示如何创建 Direct ExchangeFanout ExchangeHeaders Exchange

(1)Direct Exchange:

@Bean
public DirectExchange directExchange() {
    return new DirectExchange("direct.exchange");
}

@Bean
public Binding directBinding(Queue queue, DirectExchange directExchange) {
    return BindingBuilder.bind(queue).to(directExchange).with("direct.routing.key");
}

 Direct Exchange:直接交换机会根据 完全匹配的路由键 将消息发送到队列。只有当消息的路由键和绑定的路由键 完全一致 时,消息才会被路由到指定队列。

(2)Fanout Exchange:

@Bean
public FanoutExchange fanoutExchange() {
    return new FanoutExchange("fanout.exchange");
}

@Bean
public Binding fanoutBinding(Queue queue, FanoutExchange fanoutExchange) {
    return BindingBuilder.bind(queue).to(fanoutExchange);  // 不需要路由键
}

 Fanout Exchange:扇出交换机会将消息发送到所有绑定的队列,不需要考虑路由键。这个交换机通常用于广播消息。

(3)Headers Exchange:

@Bean
public HeadersExchange headersExchange() {
    return new HeadersExchange("headers.exchange");
}

@Bean
public Binding headersBinding(Queue queue, HeadersExchange headersExchange) {
    return BindingBuilder.bind(queue).to(headersExchange).where("header-key").matches("header-value");
}

 Headers Exchange:头交换机根据消息头的内容进行路由,而不是依赖路由键。适用于按消息的元数据进行路由的场景。

总结:

通过 Spring AMQP 的配置类,你可以非常灵活地定义 RabbitMQ 的 交换机队列绑定关系,并通过不同的路由键和交换机类型实现复杂的消息路由逻辑。以下是一些关键要点:

  1. 队列(Queue):消息的临时存储地,可以是持久化的。
  2. 交换机(Exchange):控制消息如何分发到不同的队列。
    • Direct Exchange:严格匹配路由键。
    • Topic Exchange:支持通配符匹配路由键。
    • Fanout Exchange:广播消息到所有绑定的队列。
    • Headers Exchange:根据消息头的内容进行路由。
  3. 绑定(Binding):将队列与交换机连接起来,使用路由键来决定消息的流向。

通过配置类来定义这些组件,能够简化 RabbitMQ 与 Spring 应用的集成,并且通过灵活的路由规则支持复杂的消息传递需求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【双指针算法】快乐数

1.题目解析 2.算法分析 由图可知&#xff0c;不管是最后可以变成1的还是不可以变成1的都相当于形成环了&#xff0c;只是成环处值不一样 问题转变成&#xff0c;判断链表是否有环 采用双指针&#xff0c;快慢指针算法 1.定义快慢指针2.慢指针每次向后移动一步&#xff0c;快…

初识适配器模式

适配器模式 引入 生活中的例子&#xff1a;当我们使用手机充电时&#xff0c;充电器起到了转换器的作用&#xff0c;它将家用的220伏特电压转换成适合手机充电的5伏特电压。 适配器模式的三种类型 命名原则&#xff1a;适配器的命名应基于资源如何传递给适配器来进行。 类适配…

AnaTraf | 利用多点关联数据分析和网络关键KPI监控提升IT运维效率

目录 什么是多点关联数据分析&#xff1f; 多点关联数据分析的运用场景 监控网络关键KPI的重要性 典型的网络关键KPI 案例分析&#xff1a;利用多点关联数据分析和KPI监控解决网络性能问题 结语 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具AnaTraf…

01 设计模式-创造型模式-工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。 通过使用工厂模式…

SpringBoot框架下的汽车票在线预订系统

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

基于单片机的家用无线火灾报警系统的设计

1 总体设计 本设计家用无线火灾报警系统利用单片机控制技术、传感器检测技术、GSM通信技术展开设计&#xff0c;如图2.1所示为本次系统设计的主体框图&#xff0c;系统包括单片机主控模块、温度检测模块、烟雾检测模块、按键模块、GSM通信模块、液晶显示模块、蜂鸣器报警模块。…

汽车票预订系统:SpringBoot框架的优势

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

UE5 使用Animation Budget Allocator优化角色动画性能

Animation Budget Allocator是UE内置插件&#xff0c;通过锁定动画系统所占CPU的预算&#xff0c;在到达预算计算量时对动画进行限制与优化。 开启Animation Budget Allocator需要让蒙皮Mesh使用特定的组件&#xff0c;并进行一些编辑器设置即可开启。 1.开启Animation Budget…

地球链EACO怎么和房车旅游等行业结合起来加速全球发展?

地球链EACO怎么和房车旅游等行业结合起来加速全球发展&#xff1f; 将地球链&#xff08;EACO&#xff09;与房车,旅游&#xff0c;汽车等行业结合以加速全球发展&#xff0c;可以通过以下策略&#xff1a; 智能合约与租赁平台 去中心化租赁市场&#xff1a;建立一个基于EACO的…

PCL 点云配准 基于目标对称的ICP算法(精配准)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1计算点云的法线 2.1.2基于对称误差估计的ICP配准 2.1.3可视化 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总…

【火山引擎】调用火山大模型的方法 | SDK安装 | 配置 | 客户端初始化 | 设置

豆包 (Doubao) 是字节跳动研发的大规模预训练语言模型。 目录 1 安装 2 配置访问凭证 3 客户端初始化 4 设置地域和访问域名 5 设置超时/重试次数 1 安装 通过pip安装PYTHON SDK。 pip install volcengine-python-sdk[ark] 2 配置访问凭证 获取 API Key 访问凭证具体步…

理工科考研想考计算机,湖南大学、重大、哈工大威海、山东大学,该如何选择?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 计算机对理工科同学来说&#xff0c;还是性价比很高的&#xff0c;具有很大的优势&#xff01; 一、就业前景广阔 高需求行业 在当今数字化时代&#xff0c;计算机技术几乎渗透到了各个领域&#xff0c;无论是互联网…

YOLO11 目标检测 | 自动标注 | 预标注 | 标签格式转换 | 手动校正标签

本文分享使用YOLO11进行目标检测时&#xff0c;实现模型推理预标注、自动标注、标签格式转换、以及使用Labelme手动校正标签等功能。 目录 1、预训练权重 2、生成预标注 3、分析YOLO11的目标检测格式 4、分析Labelme标注工具的格式 5、生成json标注文件 6、手动校正标签 …

SQL Server-导入和导出excel数据-注意事项

环境&#xff1a; win10&#xff0c;SQL Server 2008 R2 之前写过的放在这里&#xff1a; SqlServer_陆沙的博客-CSDN博客 https://blog.csdn.net/pxy7896/category_12704205.html 最近重启ASP.NET项目&#xff0c;在使用sql server导出和导入数据时遇到一些问题&#xff0c;特…

Qt键盘按下事件和定时器事件及事件的接收和忽略

定时器事件 //设置多少毫秒调用一次 1s1000timerId this->startTimer(1000);timerId2 this->startTimer(500);void MyWidget::timerEvent(QTimerEvent* t) {static int sec 0;//通过判断当前ID来实现不同定时器的调用时间if(t->timerId() this->timerId){//隔一…

AtCoder Beginner Contest 375 A-E 题解

我的老师让我先做最后再交&#xff0c;看正确率&#xff08;即以OI赛制打abc&#xff09; 所以我用的小号&#xff08;… …&#xff09; C 卡了老半天才出来&#xff0c;我把题读错了 难度&#xff1a; A. Seats 题意 给你一个字符串 S S S&#xff0c;仅包含 . 和 #&…

kubernets(二)

集群操作 查看集群信息 kubectl get查看各组件信息 格式&#xff1a;kubectl get 资源类型 【资源名】 【选项】 events #查看集群中的所有日志信息 -o wide # 显示资源详细信息&#xff0c;包括节点、地址... -o yaml/json #将当前资源对象输出至 yaml/json 格式文…

2024.10.20 进制转换 删除根节点为x的整个子树

进制转换 十进制转换为任意进制 #include <stdio.h> int main(){char res [32] {0};int num;int index;scanf("%d %d",&num,&index);char table[] "0123456789ABCDEF";int i 0;if(num0) res[0] 0;else if(num!0){while(num>0){res[i…

Java重修笔记 UDP 网络通信

UDP 网络通信原理 1. 类 DatagramSocket 和 DatagramPacket [数据包/数据报] 实现了基于 UDP协议网络程序。 2. UDP 数据报通过数据报套接字 DatagramSocket 发送和接收&#xff0c;系统不保证UDP数据报一定能够安全送到目的地&#xff0c;也不能确定什么时候可以抵达&#…

【机器学习】决策树算法

目录 一、决策树算法的基本原理 二、决策树算法的关键概念 三、决策树算法的应用场景 四、决策树算法的优化策略 五、代码实现 代码解释&#xff1a; 在机器学习领域&#xff0c;决策树算法是一种简单直观且易于理解的分类和回归方法。它通过学习数据特征和决策规则&#…