spring-boot对rabbitMQ的操作

一、安装rabbitMQ

  • 1、直接使用docker拉取镜像

    docker pull rabbitmq:3.8
    
  • 2、启动容器

    docker run \
     -e RABBITMQ_DEFAULT_USER=admin \
     -e RABBITMQ_DEFAULT_PASS=123456 \
     -v mq-plugins:/plugins \
     --name rabbit01 \
     --hostname rabbit01 --restart=always \
     -p 15672:15672 \
     -p 5672:5672 \
     -d \
     rabbitmq:3.8
    
  • 3、关于端口的介绍

    • 15672的给浏览器控制台使用的
    • 5672是给程序调用的
  • 4、进入到rabbit01容器中

    docker exec -it rabbit01 /bin/bash
    
  • 5、开启可视化界面操作

    rabbitmq-plugins enable rabbitmq_management
    
  • 6、客户端直接访问xx:15672

  • 7、或者直接用别人搞好的镜像

    docker run \
     -e RABBITMQ_DEFAULT_USER=admin \
     -e RABBITMQ_DEFAULT_PASS=123456 \
     -v mq-plugins:/plugins \
     --name rabbit02 \
     --hostname rabbit02 --restart=always \
     -p 15672:15672 \
     -p 5672:5672 \
     -d \
     rabbitmq:3.8-management
    

二、在spring-boot中整合

  • 1、引入依赖包

    <!--   spring boot和junit整合单元测试包     -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--   rabbitmq的包引入     -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
  • 2、在配置文件中引入配置

    server.port=8000
    spring.rabbitmq.host=localhost
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=/
    

三、简单模式

  • 1、简单模式就是一个生产者一个消费者

  • 2、生产者代码,运行下面的代码,查看可视化界面,并不存在消息,原因是因为需要手动创建simple_queue这个队列

    @SpringBootTest(classes = ProducerApplication.class)
    public class ProducerTest01 {
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        @Test
        public void test01() {
            /**
             * 第一个参数:表示队列的名称
             * 第二个参数:表示要发送的数据
             */
            rabbitTemplate.convertAndSend("simple_queue", "hello world");
        }
    }
    
  • 3、运行后查看可视化界面

    在这里插入图片描述

  • 4、定义一个消费者来消费消息

    package com.example.listener01;
    
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ConsumerListener01 {
        @RabbitListener(queues = "simple_queue")
        public void listener01(Message message) {
            String msg = new String(message.getBody());
            System.out.println("接收到的消息:" + msg);
        }
    }
    

四、work工作模式

  • 1、简单的来理解,就是在上面简单模式下增加几个消费者,如同搬砖一样的,一个搬运工搬不过来,多叫几个人来干活的性质,避免消息堆积

  • 2、同样的要先手动创建队列,在生产者端循环发送数据

    @Test
    public void test02() {
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("work_queue", "hello world");
        }
    }
    
  • 3、定义2个消费者来一起消费消息

    @Component
    public class ConsumerListener01 {
        @RabbitListener(queues = "work_queue")
        public void listener01(Message message) {
            String msg = new String(message.getBody());
            System.out.println("消费者1接收到的消息:" + msg);
        }
    }
    
  • 4、先运行消费者,然后运行生产者

    在这里插入图片描述

五、发布模式

  • 1、发布模式是指发送一个消息,希望在几个消费者那边都能接收到,上面的工作模式,一条消息被一个消费者消费了,另外一个消费者就接收不到消息,在一些场景需要给每个消费者就要用发布者模式
  • 2、根据交换机的模式可以分为以下几种
    • Fanout,广播模式,将消息全部交给所有与之绑定的队列,这里的router key为空字符串
    • Direct,将消息指定到对应的routing key
    • Topic,通配符模式,这里的routing key根据规则匹配
      • *表示一个单词
      • #表示多个单词
一、Fanout模式
  • 1、使用配置文件的方式创建交换机和队列,并且将他们绑定在一起

    package com.example.config;
    
    import org.springframework.amqp.core.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitFanoutExchangeConfiguration {
        // 交换机
        @Bean
        public Exchange fanoutExchange() {
            return ExchangeBuilder.fanoutExchange("fanout_exchange").durable(true).build();
        }
    
        // 创建一个队列
        @Bean
        public Queue fanoutQueue1() {
            return QueueBuilder.durable("fanout_queue1").build();
        }
    
        // 创建一个队列
        @Bean
        public Queue fanoutQueue2() {
            return QueueBuilder.durable("fanout_queue2").build();
        }
    
        // 队列和交换机绑定
        @Bean
        public Binding fanoutExchangeQueue01() {
            // with表示路由key
            return BindingBuilder.bind(fanoutQueue1()).to(fanoutExchange()).with("").noargs();
        }
    
        @Bean
        public Binding fanoutExchangeQueue02() {
            // with表示路由key
            return BindingBuilder.bind(fanoutQueue2()).to(fanoutExchange()).with("").noargs();
        }
    }
    
  • 2、生产者发送消息

    @Test
    public void test03() {
        rabbitTemplate.convertAndSend("fanout_exchange", "", "hello world");
    }
    
  • 3、查看可视化界面,会自动创建一个交换机和两个路由key

    在这里插入图片描述

  • 4、定义消费者

    @Component
    public class ConsumerListener01 {
        @RabbitListener(queues = "fanout_queue1")
        public void listener01(Message message) {
            String msg = new String(message.getBody());
            System.out.println("消费者1接收到的消息:" + msg);
        }
    }
    
  • 5、这时候会发现,几个消费者都会同时输出

二、Direct模式
  • 1、其实就是在上面的模式上修改创建交换机的类型,及指定类型,别的都保持不变
三、Topic模式
  • 1、在定义路由key的时候使用*或者#来表示

六、直接在监听上使用注解的方式来创建交换机等

  • 1、正常创建交换机和队列的方式有三种方式

    • 直接在可视化界面手动创建
    • 使用java api方式一个一个创建需要先创建交换机、队列,并且让队列和交换机绑定在一起
    • 直接使用注解的方式来实现
  • 2、使用注解的方式直接来创建交换机和队列

    package com.example.listener04;
    
    import org.springframework.amqp.core.ExchangeTypes;
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.annotation.Exchange;
    import org.springframework.amqp.rabbit.annotation.Queue;
    import org.springframework.amqp.rabbit.annotation.QueueBinding;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ConsumerListener01 {
        @RabbitListener(bindings = @QueueBinding(
                value = @Queue(value = "queue_01", durable = "true"),
                exchange = @Exchange(value = "direct_rabbit_exchange", type = ExchangeTypes.DIRECT),
                key = {"info", "error"}
        ))
        public void listener01(Message message) {
            String msg = new String(message.getBody());
            System.out.println("消费者1接收到的消息:" + msg);
        }
    }
    
  • 3、运行后查看rabbitmq可视化界面

  • 4、定义发送消息的方法

    public void test04() {
        rabbitTemplate.convertAndSend("direct_rabbit_exchange","error","hello world");
    }
    

七、消息丢失

  • 1、消息丢失主要存在的场景
    • 生产者投递消息的时候就丢失,比如写错了交换机的名字
    • 交换机到队列丢失,比如写错了队列名称
    • 队列到接收者数据丢失
一、开启生产者确认机制
  • 1、开启生产者确认机制

    server.port=9000
    spring.rabbitmq.host=123.56.103.229
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=/
    # 开启生产者确认机制
    spring.rabbitmq.publisher-confirm-type=correlated 
    
  • 2、重写RabbitTemplate,只要我们在容器中有一个RabbitTemplate,那么spring boot就不会用对RabbitTemplate自动化配置

    package com.example.config;
    
    import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    import org.springframework.amqp.rabbit.connection.CorrelationData;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitmqConfiguration {
        /**
         * ConnectionFactory 由于Spring Boot根据连接的配置信息实现自动化配置,在spring容器中是直接存在ConnectionFactory对象
         */
        @Bean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
            rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){
    
                @Override
                public void confirm(CorrelationData correlationData, boolean ack, String s) {
                    if (ack) {
                        System.out.println("消息正常投递到交换机中");
                    } else {
                        System.out.println("消息投递到交换机失败:"+s);
                    }
                }
            });
            return rabbitTemplate;
        }
    
    }
    
  • 3、发送消息的时候故意写错交换机的名字

    @Test
    public void test04() throws InterruptedException {
        rabbitTemplate.convertAndSend("direct_rabbit_exchange_xx","error","hello world");
        Thread.sleep(2000);
    }
    
  • 4、处理消息投送失败的方式

    • 使用数据库表来保存发送失败的消息,主要字段有:消息唯一id、消息内容、重试次数、当前消息发送状态
    • 在消息投送失败的时候重试几次
    • 定时任务将失败的批量再次发送
  • 5、在发送消息的时候传递当前唯一的识别id,这里使用uuid

    @Test
    public void test04() throws InterruptedException {
        String msgUuid = UUID.randomUUID().toString().replace("-", "");
        CorrelationData correlationData = new CorrelationData(msgUuid);
        rabbitTemplate.convertAndSend("direct_rabbit_exchange", "error", "hello world", correlationData);
        Thread.sleep(2000);
    }
    
  • 6、获取当前消息的唯一识别

    @Configuration
    public class RabbitmqConfiguration {
        /**
         * ConnectionFactory 由于Spring Boot根据连接的配置信息实现自动化配置,在spring容器中是直接存在ConnectionFactory对象
         */
        @Bean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
            rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){
    
                @Override
                public void confirm(CorrelationData correlationData, boolean ack, String s) {
                    if (ack) {
                        System.out.println("消息正常投递到交换机中");
                    } else {
                        String mesId = correlationData.getId();
                        System.out.println(mesId);
                        System.out.println("消息投递到交换机失败:"+s);
                    }
                }
            });
            return rabbitTemplate;
        }
    }
    
二、交换机到队列的时候出现问题
  • 1、当队列名称写错了,或者不存在的时候会出现这个情况

  • 2、开启生产者回调机制

    server.port=9000
    spring.rabbitmq.host=123.56.103.229
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=/
    # 开启生产者确认机制
    spring.rabbitmq.publisher-confirm-type=correlated
    # 开启生产者回调机制
    spring.rabbitmq.publisher-returns=true
    
  • 3、绑定回退函数

    package com.example.config;
    
    import org.springframework.amqp.core.ReturnedMessage;
    import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    import org.springframework.amqp.rabbit.connection.CorrelationData;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitmqConfiguration {
        /**
         * ConnectionFactory 由于Spring Boot根据连接的配置信息实现自动化配置,在spring容器中是直接存在ConnectionFactory对象
         */
        @Bean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
            ...
            // 绑定回退机制的回调函数
            rabbitTemplate.setMandatory(true);
            rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
    
                @Override
                public void returnedMessage(ReturnedMessage returnedMessage) {
                    System.out.println(returnedMessage.getMessage());
                    System.out.println(returnedMessage.getReplyCode());
                    System.out.println(returnedMessage.getReplyText());
                    System.out.println(returnedMessage.getExchange());
                    System.out.println(returnedMessage.getRoutingKey());
                }
            });
            return rabbitTemplate;
        }
    }
    
    
三、消息持久化
  • 1、rabbitmq默认是在内存中存储,当服务宕机后数据直接会丢失,消息在spring boot中持久化是因为框架帮你处理了,修改消息是否持久化可以参考下面

    @Test
    public void test04() throws InterruptedException {
        String msgUuid = UUID.randomUUID().toString().replace("-", "");
        CorrelationData correlationData = new CorrelationData(msgUuid);
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
    
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                MessageProperties messageProperties = message.getMessageProperties(); // 获取到消息属性对象
                messageProperties.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT); // 设置消息不缓存
                return message;
            }
        };
        rabbitTemplate.convertAndSend("direct_rabbit_exchange", "error", "hello world",messagePostProcessor, correlationData);
        Thread.sleep(2000);
    }
    
四、消费者消费消息不丢失
  • 1、在spring boot中消费者应答模式主要有以下几种

    • none自动应答,消费者获取到消息以后直接给rabbitmq返回ack
    • auto(默认模式),由spring boot框架根据业务执行特点决定给rabbitmqack还是uack,业务执行正常完成后返回ack,业务执行中出现异常的时候返回uack
    • manual手动应答模式,由程序员自己根据业务执行特点给rabbitmq返回对应的ack还是uack
  • 2、配置应答模式

    server.port=8000
    spring.rabbitmq.host=123.56.103.229
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=/
    # 配置应答模式
    spring.rabbitmq.listener.simple.acknowledge-mode=auto
    
八、消费限流
  • 1、在消费者端添加配置

    server.port=8000
    spring.rabbitmq.host=123.56.103.229
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=/
    spring.rabbitmq.listener.simple.acknowledge-mode=auto
    # 每次处理10个
    spring.rabbitmq.listener.simple.prefetch=10
    

九、死信队列

  • 1、在下面几种情况下会产生死信队列

    • 消息的存活时间到了
    • 队列满了,比如队列只能放10个消息,这时候发送11个消息过来,就有一个消息为死信,在队列中时间最久的那个将为成为死信队列
    • 消费被拒绝了,或者rabbitmq返回uack
  • 2、死信队列的架构图

    在这里插入图片描述

  • 3、创建死信队列

    package com.example.config;
    
    import org.springframework.amqp.core.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RabbitDlxExchangeConfiguration {
        // 创建一个死信交换机
        @Bean
        public Exchange dlxExchange() {
            return ExchangeBuilder.fanoutExchange("dlx_exchange").durable(true).build();
        }
    
        // 创建一个死信队列
        @Bean
        public Queue dlxQueue() {
            return QueueBuilder.durable("dlx_queue").maxLength(10).build();
        }
    
        // 死信交换机和死信队列绑定
        @Bean
        public Binding dlxQueueBinding() {
            return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("dead").noargs();
        }
    
        // 创建一个正常的交换机
        @Bean
        public Exchange orderExchange() {
            return ExchangeBuilder.directExchange("order_exchange").durable(true).build();
        }
    
        // 创建一个正常队列
        @Bean
        public Queue orderQueue() {
            return QueueBuilder.durable("order_queue").
                    maxLength(10).
                    deadLetterExchange("dlx_exchange"). // 死信队列的交换机
                    deadLetterRoutingKey("dead"). // 死信队列的routingKey
                    build();
        }
    
        // 正常交换机和正常队列绑定
        @Bean
        public Binding orderQueueBinding() {
            return BindingBuilder.bind(orderQueue()).to(orderExchange()).with("info").noargs();
        }
    }
    
  • 4、发送消息

    @Test
    public void test05() throws InterruptedException {
        for (int i = 0; i < 15; i++) {
            rabbitTemplate.convertAndSend("order_exchange", "info", "hello world" + i);
        }
        Thread.sleep(2000);
    }
    
  • 5、查看可视化界面,进入死信队列的是时间最早的(也就是最先发送的)

    在这里插入图片描述

  • 6、定义消费者

    package com.example.listener05;
    
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ConsumerListener01 {
        @RabbitListener(queues = "dlx_queue")
        public void listener01(Message message) {
            String msg = new String(message.getBody());
            System.out.println("接收到的死信队列消息:" + msg);
        }
    
        @RabbitListener(queues = "order_queue")
        public void listener02(Message message) {
            String msg = new String(message.getBody());
            System.out.println("接收到的订单队列消息:" + msg);
        }
    }
    

十、延迟任务

  • 1、在rabbitmq中没有真正意义上的延迟队列任务,只是采用ttl+死信队列来完成的

  • 2、延迟任务主要用于场景

    • 文章定时发布
    • 订单多少分钟后取消支付
  • 3、延迟任务的结构图

    在这里插入图片描述

  • 4、创建一个延迟任务的队列

    @Configuration
    public class RabbitDlxExchangeConfiguration {
        ...
        @Bean
        public Queue orderQueue() {
            return QueueBuilder.durable("order_queue").
                    // maxLength(10).
                    ttl(2000). // 过期时间
                    deadLetterExchange("dlx_exchange"). // 死信队列的交换机
                    deadLetterRoutingKey("dead"). // 死信队列的routingKey
                    build();
        }
    }
    
  • 5、发送消息,观察可视化界面,时间到了就会进入到死信队列中

    @Test
    public void test06() throws InterruptedException {
        rabbitTemplate.convertAndSend("order_exchange", "info", "hello world");
        Thread.sleep(2000);
    }
    
  • 6、在死信队列中监听数据来改变数据库状态

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

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

相关文章

11-28渗透

用nmap扫描靶机1进行主机发现 已知靶机1的主机在172.16.17.0/24下 扫描结果如下 根据扫描结果看开启的服务怀疑172.16.17.177是靶机1 浏览器访问172.16.17.177页面得到如下 我们知道织梦cms系统默认管理路径是dede&#xff0c;登陆管理后台可以通过地址172.16.17.177/dede/i…

第六节HarmonyOS UIAbility内页面的跳转和数据传递

一、页面跳转 在一个应用包含一个UIAbility的场景下&#xff0c;可以通过新建多个页面来实现和丰富应用的内容。这会涉及到UIAbility内页面的新建以及UIAbility内页面的跳转和数据传递。 打开DevEco Studio&#xff0c;选择一个Empty Ability工程模板&#xff0c;创建一个工程&…

深入了解Java8新特性-日期时间API:OffsetDateTime类

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概24000多字&#xff0c;预计阅读时间长需要20分钟。本篇文章的实战性、理论性较强&#xff0c;是一篇质量分数较高的技术干货文章&…

pandas教程:US Baby Names 1880–2010 1880年至2010年美国婴儿姓名

文章目录 14.3 US Baby Names 1880–2010&#xff08;1880年至2010年美国婴儿姓名&#xff09;1 Analyzing Naming Trends&#xff08;分析命名趋势&#xff09;评价命名多样性的增长“最后一个字母”的变革变成女孩名字的男孩名字&#xff08;以及相反的情况&#xff09; 14.3…

电荷泵升压/降压电路

一、升压\降压电路原理分析 1、升压电路 电荷泵升压电路 VoutVa5V 5V_PLUS0V时&#xff0c;Va给C2充电&#xff0c;C2上节点电压比C2下节点电压高Va&#xff1b; 5V_PLUS5V时&#xff0c;C2电压不能突变&#xff0c;C2上节点电压依然比C2下节点电压高Va&#xff0c;但C2下节点…

Redis 主从架构,Redis 分区,Redis哈希槽的概念,为什么要做Redis分区

文章目录 Redis 主从架构redis replication 的核心机制redis 主从复制的核心原理过程原理Redis集群的主从复制模型是怎样的&#xff1f;生产环境中的 redis 是怎么部署的&#xff1f;机器是什么配置&#xff1f;你往内存里写的是什么数据&#xff1f;说说Redis哈希槽的概念&…

智安网络|探索云安全合规要求:等保2.0时代的新趋势解析

随着信息技术的不断发展和应用的广泛普及&#xff0c;信息安全问题日益凸显&#xff0c;特别是在云计算时代&#xff0c;企业对于云平台的安全保障需求更为迫切。等级保护&#xff08;等保&#xff09;作为我国信息安全的基本要求&#xff0c;已经进入了2.0时代&#xff0c;对于…

ArkTS-共享元素转场动画

共享元素转场动画 在不同页面间&#xff0c;有使用相同的元素&#xff08;例如同一幅图&#xff09;的场景&#xff0c;可以使用共享元素转场动画衔接。为了突出不同页面间相同元素的关联性&#xff0c;可为它们添加共享元素转场动画。如果相同元素在不同页面间的大小有明显差异…

有没有不含亚硫酸盐的葡萄酒?

没有完全不含亚硫酸盐的葡萄酒&#xff0c;有机葡萄酒和生物动力葡萄酒中也会含有少量天然 亚硫酸盐。因为它是在发酵过程中产生的一种化合物&#xff0c;所以不可能酿造无亚硫酸盐的葡萄酒。 在大多数葡萄酒国家都有葡萄酒法律规定&#xff0c;如果葡萄酒超过特定的亚硫酸盐水…

【华为OD题库-043】二维伞的雨滴效应-java

题目 普通的伞在二维平面世界中&#xff0c;左右两侧均有一条边&#xff0c;而两侧伞边最下面各有一个伞坠子&#xff0c;雨滴落到伞面&#xff0c;逐步流到伞坠处&#xff0c;会将伞坠的信息携带并落到地面&#xff0c;随着日积月累&#xff0c;地面会呈现伞坠的信息。 1、为了…

JavaScript的学习

HTML的学习-CSDN博客 从html的学习中 其实我已经用到了 JavaScript的脚本 &#xff08;GPT&#xff09; 例如 echo <script>alert("账号密码错误"); window.location"index.html";</script>; 弹窗 然后定位到 index.html 这里能够让我们更…

C++数据结构:图

目录 一. 图的基本概念 二. 图的存储结构 2.1 邻接矩阵 2.2 邻接表 三. 图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四. 最小生成树 4.1 最小生成树获取策略 4.2 Kruskal算法 4.3 Prim算法 五. 最短路径问题 5.1 Dijkstra算法 5.2 Bellman-Ford算法 5.3 Floyd-…

二十章总结

线程简介 Windows操作系统是多任务操作系统&#xff0c;它以进程为单位。一个进程是一个包含有自身地址的程序&#xff0c;每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进程。系统可以分配给每一个进程有一段有限的使用CPU的时间&#xff08;也可以称为C…

使用NVM管理多个Nodejs版同时本支持vue2、vue3

1.安装nvm,下载地址&#xff1a; https://github.com/coreybutler/nvm-windows/releases/tag/1.1.12 2.nvm常用命令 Usage:nvm arch : Show if node is running in 32 or 64 bit mode.nvm current : Display active version.nvm debug …

python基础练习题库实验6

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 根据以下规范编写一个函数: 函数名称:triple输入参数:1个输入参数数据类型字符串返回值:函数返回1个字符串值。该字符串由每个字符重复3次的句子构成。例如,如果句子是Uni,…

vue中:计算属性computed

1. 在computed中定义计算属性方法根据已有的数据进行计算返回一个要显示的新数据 2. 在页面中使用{{计算属性名}}来显示返回的数据 3. computed: 内部有缓存, 多处读取只计算一次 4. 计算属性默认相当于只有getter来根据已有数据计算返回一个新数据值, 也可以指定setter来监…

对象的内部结构

在HotSpot 虚拟机里&#xff0c;对象在堆内存中的存储布局可以划分为三个部分&#xff1a;对象头&#xff08; Header &#xff09;、实例数据&#xff08;Instance Data &#xff09;和对齐填充&#xff08; Padding &#xff09;。 对象头 Mark Word&#xff08;标记字段&a…

初识《树》

目录 前言&#xff1a; 树的概念及结构&#xff1a; 1.概念 2.结构 3.树的相关概念 4.树的表示 5.树的实际应用 二叉树的概念及结构&#xff1a; 1.概念 2.特殊二叉树 ​编辑 3.二叉树的性质 对于满二叉树 对于完全二叉树&#xff1a; 4.二叉树的存储结构 堆 …

【安卓】安卓xTS之Media模块 学习笔记(1) xTS介绍

1.背景 Media的安卓xTS相关测试和功能修复已经进行了一段时间了。 在此整理总结下xTS工作总结&#xff0c;留待后续查阅整理。 2. xTS介绍 - 什么是xTS 谷歌的xTS是对谷歌发布的CTS/GTS/VTS/STS/BTS/CTS-on-GSI等一系列测试的统称。 因为安卓系统比较庞大&#xff0c;模块多…

Python语言学习笔记之二(基础语法)

本课程对于有其它语言基础的开发人员可以参考和学习&#xff0c;同时也是记录下来&#xff0c;为个人学习使用&#xff0c;文档中有此不当之处&#xff0c;请谅解。 Python几种字符串的表示&#xff1a; 在Python中&#xff0c;字符串是一种基本的数据类型&#xff0c;可以使…