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

RabbitMQ 的七种消息传递形式

文章目录

  • 一、RabbitMQ 架构简介
    • 二、准备工作
  • 三、消息收发
    • 1. Hello World
    • 2. Work queues
    • 3. Publish/Subscrite
      • 3.1. Direct
      • 3.2. Fanout
      • 3.3. Topic
      • 3.4. Header
    • 4. Routing
    • 5. Topics

大部分情况下,我们可能都是在 Spring Boot 或者 Spring Cloud 环境下使用 RabbitMQ,因此本文我也主要从这两个方面来和大家分享 RabbitMQ 的用法。

一、RabbitMQ 架构简介

一图胜千言,如下:
在这里插入图片描述
这张图中涉及到如下一些概念:

生产者(Publisher):发布消息到 RabbitMQ 中的交换机(Exchange)上。
交换机(Exchange):和生产者建立连接并接收生产者的消息。
消费者(Consumer):监听 RabbitMQ 中的 Queue 中的消息。
队列(Queue):Exchange 将消息分发到指定的 Queue,Queue 和消费者进行交互。
路由(Routes):交换机转发消息到队列的规则。

二、准备工作

大家知道,RabbitMQ 是 AMQP 阵营里的产品,Spring Boot 为 AMQP 提供了自动化配置依赖 spring-boot-starter-amqp,因此首先创建 Spring Boot 项目并添加该依赖,如下:

在这里插入图片描述
项目创建成功后,在 application.properties 中配置 RabbitMQ 的基本连接信息,如下:

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672

接下来进行 RabbitMQ 配置,在 RabbitMQ 中,所有的消息生产者提交的消息都会交由 Exchange 进行再分配,Exchange 会根据不同的策略将消息分发到不同的 Queue 中。

RabbitMQ 官网介绍了如下几种消息分发的形式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我主要和大家介绍前六种消息收发方式。

三、消息收发

1. Hello World

咦?这个咋没有交换机?这个其实是默认的交换机,我们需要提供一个生产者一个队列以及一个消费者。消息传播图如下:
在这里插入图片描述
来看看代码实现:

先来看看队列的定义:

@Configuration
public class HelloWorldConfig {public static final String HELLO_WORLD_QUEUE_NAME = "hello_world_queue";@BeanQueue queue1() {return new Queue(HELLO_WORLD_QUEUE_NAME);}
}

再来看看消息消费者的定义:

@Component
public class HelloWorldConsumer {@RabbitListener(queues = HelloWorldConfig.HELLO_WORLD_QUEUE_NAME)public void receive(String msg) {System.out.println("msg = " + msg);}
}

消息发送:

@SpringBootTest
class RabbitmqdemoApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testvoid contextLoads() {rabbitTemplate.convertAndSend(HelloWorldConfig.HELLO_WORLD_QUEUE_NAME, "hello");}}

这个时候使用的其实是默认的直连交换机(DirectExchange),DirectExchange 的路由策略是将消息队列绑定到一个 DirectExchange 上,当一条消息到达 DirectExchange 时会被转发到与该条消息routing key相同的 Queue 上,例如消息队列名为 “hello-queue”,则 routingkey 为 “hello-queue” 的消息会被该消息队列接收。

2. Work queues

这种情况是这样的:

一个生产者,一个默认的交换机(DirectExchange),一个队列,两个消费者,如下图:
在这里插入图片描述
一个队列对应了多个消费者,默认情况下,由队列对消息进行平均分配,消息会被分到不同的消费者手中。消费者可以配置各自的并发能力,进而提高消息的消费能力,也可以配置手动 ack,来决定是否要消费某一条消息。

先来看并发能力的配置,如下:

@Component
public class HelloWorldConsumer {@RabbitListener(queues = HelloWorldConfig.HELLO_WORLD_QUEUE_NAME)public void receive(String msg) {System.out.println("receive = " + msg);}@RabbitListener(queues = HelloWorldConfig.HELLO_WORLD_QUEUE_NAME,concurrency = "10")public void receive2(String msg) {System.out.println("receive2 = " + msg+"------->"+Thread.currentThread().getName());}
}

可以看到,第二个消费者我配置了 concurrency 为 10,此时,对于第二个消费者,将会同时存在 10 个子线程去消费消息。

启动项目,在 RabbitMQ 后台也可以看到一共有 11 个消费者。
在这里插入图片描述
此时,如果生产者发送 10 条消息,就会一下都被消费掉。

消息发送方式如下:

@SpringBootTest
class RabbitmqdemoApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testvoid contextLoads() {for (int i = 0; i < 10; i++) {rabbitTemplate.convertAndSend(HelloWorldConfig.HELLO_WORLD_QUEUE_NAME, "hello");}}}

消息消费日志如下:
在这里插入图片描述
可以看到,消息都被第一个消费者消费了。但是小伙伴们需要注意,事情并不总是这样(多试几次就可以看到差异),消息也有可能被第一个消费者消费(只是由于第二个消费者有十个线程一起开动,所以第二个消费者消费的消息占比更大)。

当然消息消费者也可以开启手动 ack,这样可以自行决定是否消费 RabbitMQ 发来的消息,配置手动 ack 的方式如下:

spring.rabbitmq.listener.simple.acknowledge-mode=manual

消费代码如下:

@Component
public class HelloWorldConsumer {@RabbitListener(queues = HelloWorldConfig.HELLO_WORLD_QUEUE_NAME)public void receive(Message message,Channel channel) throws IOException {System.out.println("receive="+message.getPayload());channel.basicAck(((Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG)),true);}@RabbitListener(queues = HelloWorldConfig.HELLO_WORLD_QUEUE_NAME, concurrency = "10")public void receive2(Message message, Channel channel) throws IOException {System.out.println("receive2 = " + message.getPayload() + "------->" + Thread.currentThread().getName());channel.basicReject(((Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG)), true);}
}

此时第二个消费者拒绝了所有消息,第一个消费者消费了所有消息。

这就是 Work queues 这种情况。

3. Publish/Subscrite

再来看发布订阅模式,这种情况是这样:

一个生产者,多个消费者,每一个消费者都有自己的一个队列,生产者没有将消息直接发送到队列,而是发送到了交换机,每个队列绑定交换机,生产者发送的消息经过交换机,到达队列,实现一个消息被多个消费者获取的目的。需要注意的是,如果将消息发送到一个没有队列绑定的 Exchange上面,那么该消息将会丢失,这是因为在 RabbitMQ 中 Exchange 不具备存储消息的能力,只有队列具备存储消息的能力,如下图:
在这里插入图片描述
这种情况下,我们有四种交换机可供选择,分别是:

Direct
Fanout
Topic
Header
我分别来给大家举一个简单例子看下。

3.1. Direct

DirectExchange 的路由策略是将消息队列绑定到一个 DirectExchange 上,当一条消息到达 DirectExchange 时会被转发到与该条消息 routing key 相同的 Queue 上,例如消息队列名为 “hello-queue”,则 routingkey 为 “hello-queue” 的消息会被该消息队列接收。DirectExchange 的配置如下:

@Configuration
public class RabbitDirectConfig {public final static String DIRECTNAME = "javaboy-direct";@BeanQueue queue() {return new Queue("hello-queue");}@Bean
DirectExchange directExchange() {return new DirectExchange(DIRECTNAME, true, false);}@BeanBinding binding() {return BindingBuilder.bind(queue()).to(directExchange()).with("direct");}
}
  • 首先提供一个消息队列Queue,然后创建一个DirectExchange对象,三个参数分别是名字,重启后是否依然有效以及长期未用时是否删除。
  • 创建一个Binding对象将Exchange和Queue绑定在一起。
  • DirectExchange和Binding两个Bean的配置可以省略掉,即如果使用DirectExchange,可以只配置一个Queue的实例即可。

再来看看消费者:

@Component
public class DirectReceiver {@RabbitListener(queues = "hello-queue")public void handler1(String msg) {System.out.println("DirectReceiver:" + msg);}
}

通过 @RabbitListener 注解指定一个方法是一个消息消费方法,方法参数就是所接收到的消息。然后在单元测试类中注入一个 RabbitTemplate 对象来进行消息发送,如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testpublic void directTest() {rabbitTemplate.convertAndSend("hello-queue", "hello direct!");}
}

最终执行结果如下:
在这里插入图片描述

3.2. Fanout

FanoutExchange 的数据交换策略是把所有到达 FanoutExchange 的消息转发给所有与它绑定的 Queue 上,在这种策略中,routingkey 将不起任何作用,FanoutExchange 配置方式如下:

@Configuration
public class RabbitFanoutConfig {public final static String FANOUTNAME = "sang-fanout";@BeanFanoutExchange fanoutExchange() {return new FanoutExchange(FANOUTNAME, true, false);}@BeanQueue queueOne() {return new Queue("queue-one");}@BeanQueue queueTwo() {return new Queue("queue-two");}@BeanBinding bindingOne() {return BindingBuilder.bind(queueOne()).to(fanoutExchange());}@BeanBinding bindingTwo() {return BindingBuilder.bind(queueTwo()).to(fanoutExchange());}
}

在这里首先创建 FanoutExchange,参数含义与创建 DirectExchange 参数含义一致,然后创建两个 Queue,再将这两个 Queue 都绑定到 FanoutExchange 上。接下来创建两个消费者,如下:

@Component
public class FanoutReceiver {@RabbitListener(queues = "queue-one")public void handler1(String message) {System.out.println("FanoutReceiver:handler1:" + message);}@RabbitListener(queues = "queue-two")public void handler2(String message) {System.out.println("FanoutReceiver:handler2:" + message);}
}

两个消费者分别消费两个消息队列中的消息,然后在单元测试中发送消息,如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testpublic void fanoutTest() {rabbitTemplate.convertAndSend(RabbitFanoutConfig.FANOUTNAME, null, "hello fanout!");}
}

注意这里发送消息时不需要 routingkey,指定 exchange 即可,routingkey 可以直接传一个 null

最终执行日志如下:
在这里插入图片描述

3.3. Topic

TopicExchange 是比较复杂但是也比较灵活的一种路由策略,在 TopicExchange 中,Queue 通过 routingkey 绑定到 TopicExchange 上,当消息到达 TopicExchange 后,TopicExchange 根据消息的 routingkey 将消息路由到一个或者多个 Queue 上。TopicExchange 配置如下:

@Configuration
public class RabbitTopicConfig {public final static String TOPICNAME = "sang-topic";@BeanTopicExchange topicExchange() {return new TopicExchange(TOPICNAME, true, false);}@BeanQueue xiaomi() {return new Queue("xiaomi");}@BeanQueue huawei() {return new Queue("huawei");}@BeanQueue phone() {return new Queue("phone");}@BeanBinding xiaomiBinding() {return BindingBuilder.bind(xiaomi()).to(topicExchange()).with("xiaomi.#");}@BeanBinding huaweiBinding() {return BindingBuilder.bind(huawei()).to(topicExchange()).with("huawei.#");}@BeanBinding phoneBinding() {return BindingBuilder.bind(phone()).to(topicExchange()).with("#.phone.#");}
}
  • 首先创建 TopicExchange,参数和前面的一致。然后创建三个 Queue,第一个 Queue 用来存储和 “xiaomi” 有关的消息,第二个 Queue 用来存储和 “huawei” 有关的消息,第三个 Queue 用来存储和 “phone” 有关的消息。
  • 将三个 Queue 分别绑定到 TopicExchange 上,第一个 Binding 中的 “xiaomi.#” 表示消息的 routingkey 凡是以 “xiaomi” 开头的,都将被路由到名称为 “xiaomi” 的 Queue 上,第二个 Binding 中的 “huawei.#” 表示消息的 routingkey 凡是以 “huawei” 开头的,都将被路由到名称为 “huawei” 的 Queue 上,第三个 Binding 中的 “#.phone.#” 则表示消息的 routingkey 中凡是包含 “phone” 的,都将被路由到名称为 “phone” 的 Queue 上。

接下来针对三个 Queue 创建三个消费者,如下:

@Component
public class TopicReceiver {@RabbitListener(queues = "phone")public void handler1(String message) {System.out.println("PhoneReceiver:" + message);}@RabbitListener(queues = "xiaomi")public void handler2(String message) {System.out.println("XiaoMiReceiver:"+message);}@RabbitListener(queues = "huawei")public void handler3(String message) {System.out.println("HuaWeiReceiver:"+message);}
}

然后在单元测试中进行消息的发送,如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testpublic void topicTest() {rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,
"xiaomi.news","小米新闻..");rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,
"huawei.news","华为新闻..");rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,
"xiaomi.phone","小米手机..");rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,
"huawei.phone","华为手机..");rabbitTemplate.convertAndSend(RabbitTopicConfig.TOPICNAME,
"phone.news","手机新闻..");}
}

根据 RabbitTopicConfig 中的配置,第一条消息将被路由到名称为 “xiaomi” 的 Queue 上,第二条消息将被路由到名为 “huawei” 的 Queue 上,第三条消息将被路由到名为 “xiaomi” 以及名为 “phone” 的 Queue 上,第四条消息将被路由到名为 “huawei” 以及名为 “phone” 的 Queue 上,最后一条消息则将被路由到名为 “phone” 的 Queue 上。

3.4. Header

HeadersExchange 是一种使用较少的路由策略,HeadersExchange 会根据消息的 Header 将消息路由到不同的 Queue 上,这种策略也和 routingkey无关,配置如下:

@Configuration
public class RabbitHeaderConfig {public final static String HEADERNAME = "javaboy-header";@BeanHeadersExchange headersExchange() {return new HeadersExchange(HEADERNAME, true, false);}@BeanQueue queueName() {return new Queue("name-queue");}@BeanQueue queueAge() {return new Queue("age-queue");}@BeanBinding bindingName() {Map<String, Object> map = new HashMap<>();map.put("name", "sang");return BindingBuilder.bind(queueName()).to(headersExchange()).whereAny(map).match();}@BeanBinding bindingAge() {return BindingBuilder.bind(queueAge()).to(headersExchange()).where("age").exists();}
}

这里的配置大部分和前面介绍的一样,差别主要体现的 Binding 的配置上,第一个 bindingName 方法中,whereAny 表示消息的 Header 中只要有一个 Header 匹配上 map 中的 key/value,就把该消息路由到名为 “name-queue” 的 Queue 上,这里也可以使用 whereAll 方法,表示消息的所有 Header 都要匹配。whereAny 和 whereAll 实际上对应了一个名为 x-match 的属性。bindingAge 中的配置则表示只要消息的 Header 中包含 age,不管 age 的值是多少,都将消息路由到名为 “age-queue” 的 Queue 上。

接下来创建两个消息消费者:

@Component
public class HeaderReceiver {@RabbitListener(queues = "name-queue")public void handler1(byte[] msg) {System.out.println("HeaderReceiver:name:"+ new String(msg, 0, msg.length));}@RabbitListener(queues = "age-queue")public void handler2(byte[] msg) {System.out.println("HeaderReceiver:age:"+ new String(msg, 0, msg.length));}
}

注意这里的参数用 byte 数组接收。然后在单元测试中创建消息的发送方法,这里消息的发送也和 routingkey 无关,如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqApplicationTests {@AutowiredRabbitTemplate rabbitTemplate;@Testpublic void headerTest() {Message nameMsg = MessageBuilder.withBody("hello header! name-queue".getBytes()).setHeader("name", "sang").build();Message ageMsg = MessageBuilder.withBody("hello header! age-queue".getBytes()).setHeader("age", "99").build();rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME, null, ageMsg);rabbitTemplate.send(RabbitHeaderConfig.HEADERNAME, null, nameMsg);}
}

这里创建两条消息,两条消息具有不同的 header,不同 header 的消息将被发到不同的 Queue 中去。

最终执行效果如下:
在这里插入图片描述

4. Routing

这种情况是这样:

一个生产者,一个交换机,两个队列,两个消费者,生产者在创建 Exchange 后,根据 RoutingKey 去绑定相应的队列,并且在发送消息时,指定消息的具体 RoutingKey 即可。

如下图:
在这里插入图片描述
这个就是按照 routing key 去路由消息,我这里就不再举例子了,大家可以参考 3.3.1 小结。

5. Topics

这种情况是这样:

一个生产者,一个交换机,两个队列,两个消费者,生产者创建 Topic 的 Exchange 并且绑定到队列中,这次绑定可以通过 * # 关键字,对指定 RoutingKey 内容,编写时注意格式 xxx.xxx.xxx 去编写。

如下图:
在这里插入图片描述
这个我也就不举例啦,前面 3.3.3 小节已经举过例子了,不再赘述。

相关文章:

RabbitMQ 的七种消息传递形式

文章目录 一、RabbitMQ 架构简介二、准备工作 三、消息收发1. Hello World2. Work queues3. Publish/Subscrite3.1. Direct3.2. Fanout3.3. Topic3.4. Header 4. Routing5. Topics 大部分情况下&#xff0c;我们可能都是在 Spring Boot 或者 Spring Cloud 环境下使用 RabbitMQ&…...

开源免费跨平台数据同步工具-Syncthing

Syncthing是一款开源免费跨平台的文件同步工具&#xff0c;是基于P2P技术实现设备间的文件同步&#xff0c;所以它的同步是去中心化的&#xff0c;即你并不需要一个服务器&#xff0c;故不需要担心这个中心的服务器给你带来的种种限制&#xff0c;而且类似于torrent协议&#x…...

java语言中受检异常和非受检异常的区别是什么?

在Java语言中&#xff0c;异常可以分为两种类型&#xff1a;受检异常&#xff08;Checked Exception&#xff09;和非受检异常&#xff08;Unchecked Exception&#xff09;。 受检异常&#xff08;Checked Exception&#xff09;&#xff1a;这是编译器要求必须进行处理的异常…...

vue3 element-plus el-table表头冻结,表头吸顶

一.使用方式 在main.ts页面创建 vue指令 import { createSticky } from /utils/stickyconst app createApp(App)createSticky(app)...app.mount(#app);在el-table标签上使用 v-sticky <div class"table-box"><!--此处的 .table-box 是会出现滚动条的DOM元…...

mysql中删除数据后,新增数据时id会跳跃,主键自增id不连续

引言&#xff1a; 在使用MySQL数据库时&#xff0c;有时候我们需要删除某些记录&#xff0c;但是删除记录后可能会导致表中的id不再连续排序。 如何实现删除记录后让id重新排序的功能。 如图&#xff1a; 删除数据后&#xff0c;中间的id不会自动连续。 下面有两种方法进行重…...

todesk连接ubuntu显示当前系统并无桌面环境,或无显示器,无法显示远程桌面,您需要自行安装X11桌面环境,或者使用终端文件功能

ToDesk远程遇到的问题如上图&#xff0c;换向日葵直接黑屏&#xff1b; 问题原因 截止发文时间&#xff0c;Todesk只支持X11协议&#xff0c;没有适配最新的Wayland协议&#xff0c;所以我们需要把窗口系统调整为X11才可以。 解决方法 修改配置文件&#xff0c;关闭wayland su…...

webpack学习-1.起步

webpack学习-1.起步 1.基础设置2.配置文件的引入3.总结 1.基础设置 首先 webpack是干嘛的呢&#xff0c;用官网的一张图 Webpack 是一个现代的静态模块打包工具。它主要用于将前端应用程序中的各种资源&#xff08;例如 JavaScript、CSS、图片等&#xff09;打包成一个或多个…...

GNU Radio 教程

初学者教程 GNU 无线电简介 什么是 GNU 无线电&#xff1f;安装 GNU 无线电你的第一个流程图 流程图基础知识 GRC 中的 Python 变量流程图中的变量运行时更新变量信号数据类型转换数据类型包装位流和向量层次块和参数 创建和修改 Python 块 创建你的第一个块带向量的 Pyt…...

Linux 下命令行启动与关闭WebLogic的相关服务

WebLogic 的服务器类型 WebLogic提供了三种类型的服务器&#xff1a; 管理服务器节点服务器托管服务器 示例和关系如下图&#xff1a; 对应三类服务器&#xff0c; 就有三种启动和关闭的方式。本篇介绍使用命令行脚本的方式启动和关闭这三种类型的服务器。 关于WebLogic 的…...

模型量化相关知识汇总

量化&反量化 量化操作可以将浮点数转换为低比特位数据表示,比如int8和 uint8. Q(x_fp32, scale, zero_point) round(x_fp32/scale) zero_point,量化后的数据可以经过反量化操作来获取浮点数 x_fp32 (Q - zero_point)* scale pytorch中 quantize_per_tensor的解释 py…...

yum 操作,出现Cannot retrieve metalink for repository: epel/x86_64

详细报错如下&#xff1a; Loaded plugins: fastestmirror Determining fastest mirrorsOne of the configured repositories failed (Unknown),and yum doesnt have enough cached data to continue. At this point the onlysafe thing yum can do is fail. There are a few…...

MySQL 8.2 Command Line Client闪退

原因一 服务没有打开 原因二 找不到my.ini文件 原因一的解决方法 操作1进入管理 操作2选择服务 1 2 3 操作3选择MySQL服务并打开 原因二的解决方法 查找目录中是否有my.ini文件 C:\Program Files\MySQL\MySQL Server 8.2&#xff08;一般在这个目录下&#xff09; 有时…...

【Geoserver】SLD点位样式(PointSymbolizer)设计全通

SLD文件可以控制geoserver的样式管理&#xff0c;这里专门针对点位进行设计&#xff0c;首先点位的设计需要用到这面这个大标签 之前的项目中已经用到了很多关于面的样式管理&#xff0c;这里新学习的是关于点的样式管理 PointSymbolizer 参考资料地址&#xff1a;https://doc…...

大数据基础设施搭建 - 数据装载

文章目录 一、概述二、数据装载&#xff08;HDFS -> Hive&#xff09;2.1 创建Hive表2.1.1 业务全量表建表语句2.1.2 业务增量表建表语句2.1.3 流量增量表建表语句 2.2 数据装载2.2.1 初始化装载省份和地区表2.2.2 业务数据装载&#xff08;1&#xff09; 开发脚本&#xff…...

医药行业:轻松学会超低温冰箱技能

超低温冰箱在医疗、科研和生物领域中扮演着至关重要的角色&#xff0c;用于存储和保护对温度极为敏感的样品和药品。 然而&#xff0c;由于这些冰箱内的温度波动可能导致样品的损坏&#xff0c;因此对超低温冰箱的监控变得至关重要。 客户案例 医疗研究机构 上海某医疗研究机…...

信息化系列——企业信息化建设(2)

企业信息化建设常见问题 1、信息化意识薄弱 目前&#xff0c;仍有许多企业的管理者在信息化方面表现出薄弱的认识&#xff0c;他们对信息化建设的重视程度显得捉襟见肘。结果&#xff0c;企业在信息化建设的人力、物力支持方面投入甚微&#xff0c;导致信息化建设难以完成顶层…...

php爬虫去抓取京东优惠券代码,事半功倍

没事总分享一些抓取方案的简单代码&#xff0c;实际中爬虫涉及的内容知识点其实很多&#xff0c;一般数据较少或非频繁的时候还是容易处理的。但是简单的时候也有问题的时候&#xff0c;比如ip经常被封&#xff0c;被限制等等问题。如果抓取的时候时间短或可以外赚费用的时候还…...

电子书制作神器!错过等十年

众所周知&#xff0c;随着科技的飞速发展&#xff0c;电子书已成为越来越多人的首选阅读方式。但制作电子书并不费力&#xff0c;一个制作电子书的神器就能解决这些问题。 那这款神器究竟有何魅力&#xff1f;它能帮助我们制作出怎样的电子书&#xff1f; 首先&#xff0c;这款…...

文献速递:机器学习在超声非破坏性评估中的合成和增强训练数据综述(第二部分)— 合成数据生成方法用于超声波测试

Title 题目 A review of synthetic and augmented training data for machine learning in ultrasonic non-destructive evaluation 机器学习在超声无损检测中合成与增强训练数据的综述 01 文献速递介绍 注&#xff1a;原文篇幅较长&#xff0c;这里分多次进行分享。近年来&…...

gitlab高级功能之mirroring - push mirroring(一)

今天给大家介绍一个gitlab很高级也是非常有用的功能 - gitlab的mirroring&#xff0c;你可以将仓库镜像到外部或从外部镜像仓库过来&#xff0c;从而可以实现分支、标签和提交的自动同步。 文章目录 1. mirroring的实现方式2. push mirroring2.1 简介2.2 说明 3. 配置推送镜像3…...

【PUSDN】WebStorm中报错Switch language version to React JSX

简述 WebStorm中报错Switch language version to React JSX 可能本页面的写法是其他语法。所以可以不用管。 测试项目&#xff1a;ant design vue pro 前情提示 系统&#xff1a; 一说 同步更新最新版、完整版请移步PUSDN Powered By PUSDN - 平行宇宙软件开发者网www.pusdn…...

【算法思考记录】力扣1094.拼车 C++【树状数组】

拼车问题&#xff08;LeetCode 1094&#xff09;的解析与C实现 Problem: 1094. 拼车 题目背景 在本题中&#xff0c;我们需要处理一个拼车的问题。假设一辆车有固定的座位容量&#xff0c;我们需要根据乘客的上车和下车地点&#xff0c;判断车辆是否能够在整个行程中满足不超过…...

业务场景中Hive解析Json常用案例

业务场景中Hive解析Json常用案例 json在线工具 json格式转换在线工具 https://tool.lu/json/format格式互转&#xff1a; // 格式化可以合并整行显示 {"name":"John Doe","age":35,"email":"johnexample.com"}// 格式化…...

垃圾回收与内存泄漏

前端面试大全JavaScript垃圾回收与内存泄漏 &#x1f31f;经典真题 &#x1f31f;什么是内存泄露 &#x1f31f;JavaScript 中的垃圾回收 &#x1f31f;标记清除 &#x1f31f;引用计数 &#x1f31f;真题解答 &#x1f31f;总结 &#x1f31f;经典真题 请介绍一下 Jav…...

SQL Server 2016(创建数据表)

1、需求描述。 在名为“class”的数据库中创建表&#xff0c;表名称为“course”&#xff0c;其中要包含序号、课程、课程编号、学分、任课教师、上课地点、开始时间、结束时间、备注等列。 设置各个字段的数据类型。其中&#xff0c;"序号"列为标识列&#xff0c;从…...

mysql配置文件低于8.0版本慎用(头部声明的路径请自行替换或删减)(干货)

[mysqld] character-set-server utf8mb4 collation-server utf8mb4_general_ci init_connectSET NAMES utf8mb4datadir/data/mysql/data socket/data/mysql/mysql.socklog-error/data/mysql/log/mysql_error.log pid-file/data/mysql/mysqld.pidserver_id1 #如果做集群不同my…...

给WordPress文章添加广告位

/* * WordPress 在文章内容中间插入广告//由www.wwttl.com提供学习 */ //在文章内容的第二段后面插入广告 add_filter( the_content, prefix_insert_post_ads ); function prefix_insert_post_ads( $content ) { $ad_code <div>广告代码放这里</div>;if ( is_sing…...

[GPT-1]论文实现:Improving Language Understanding by Generative Pre-Training

Efficient Graph-Based Image Segmentation 一、完整代码二、论文解读2.1 GPT架构2.2 GPT的训练方式Unsupervised pre_trainingSupervised fine_training 三、过程实现3.1 导包3.2 数据处理3.3 模型构建3.4 模型配置 四、整体总结 论文&#xff1a;Improving Language Understa…...

23种设计模式之C++实践(一)

23种设计模式之C++实践 1. 简介2. 基础知识3. 设计模式(一)创建型模式1. 单例模式——确保对象的唯一性1.2 饿汉式单例模式1.3 懒汉式单例模式比较IoDH单例模式总结2. 简单工厂模式——集中式工厂的实现简单工厂模式总结3. 工厂方法模式——多态工厂的实现工厂方法模式总结4.…...

华为OD机试 - 园区参观路径(Java JS Python C)

题目描述 园区某部门举办了Family Day,邀请员工及其家属参加; 将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角; 家属参观园区时,只能向右和向下园区前进,求从起始园区到终点园区会有多少条不同的参观路径。 输入描述 第一行为园区的长和宽; 后…...

professional wordpress/百度网盘下载速度慢破解方法

A Better You, A Bigger World说起英文学习&#xff0c;很多家长都会头疼&#xff1a;想学好英语&#xff0c;除了背单词、学语法&#xff0c;还有哪些更有效的办法&#xff1f;想让孩子多接触英文原著&#xff0c;但孩子觉得枯燥又读不懂&#xff0c;怎么办&#xff1f;全球未…...

乐清做网站/微信管理系统软件

“数据星河”系列活动—大数据人才培养现状和思考...

专业的上海网站建设公司哪家好/查询网站域名

Flutter中的第三方包 指纹识别、触摸ID、面部ID、密码、pin或图案 local_auth...

用vs2012做网站案例/百度下载官方下载安装

今天要做一个小Demo用来获取测试数据的&#xff0c;碰到一个特别基础性的语言基础问题&#xff0c;Mark下来。如果双目运算符号的左右两个数值类型为整型&#xff0c;则得出来的数值也为整型&#xff0c;例如一下一个小Demo&#xff1a;inta 64;intb 65;floatf (float)(b/a);f…...

网站建设策划方案如何写/小程序seo推广技巧

问题&#xff1a;RadioButton中使用android:gravity"center"使其图片文字居中&#xff0c;在我的华为荣耀7手机上居中显示了&#xff0c;但在HUAWEI G606-T00却显示在右侧了。 解决&#xff1a;在RadioButton中设置属性 android:paddingLeft"0dp" 或者 and…...

常德网站设计/免费有效的推广平台

Windows下安装配置免安装MySQL5.7服务器 1、下载、解压安装包 从MySQL官方网站上下载mysql-5.7.19-winx64.zip 下载完成后&#xff0c;把安装包解压到D:\DevSoftware\mysql57\目录下&#xff0c;会生成一个mysql-5.7.19-winx64目录。现在MySQL的目录就是D:\DevSoftware\mysql57…...