怎么做原创动漫视频网站/郑州关键词seo
Spring Boot + MySQL: 多线程查询与联表查询性能对比分析
背景
在现代 Web 应用开发中,数据库性能是影响系统响应时间和用户体验的关键因素之一。随着业务需求的不断增长,单表查询和联表查询的效率问题日益凸显。特别是在 Spring Boot 项目中,结合 MySQL 数据库进行复杂查询时,如何优化查询性能已成为开发者必须面对的重要问题。
在本实验中,我们使用了 Spring Boot 框架结合 MySQL 数据库,进行了两种常见查询方式的性能对比:多线程查询 和 联表查询。通过对比这两种查询方式的响应时间,本文旨在探讨在实际业务场景中,选择哪种方式能带来更高的查询效率,尤其是在面对大数据量和复杂查询时的性能表现。
实验目的
本实验的主要目的是通过对比以下两种查询方式的性能,帮助开发者选择在不同业务场景下的查询方式:
- 联表查询(使用 SQL 语句中的 LEFT JOIN 等连接操作)
- 多线程查询(通过 Spring Boot 异步处理,分批查询不同表的数据)
实验环境
-
开发框架:Spring Boot
-
数据库:MySQL
-
数据库表结构:
test_a
:主表,包含与其他表(test_b
、test_c
、test_d
、test_e
)的关联字段。test_b
、test_c
、test_d
、test_e
:附表,分别包含不同的数据字段。
这些表通过外键(逻辑)关联,
test_a
表中的test_b_id
、test_c_id
、test_d_id
和test_e_id
字段指向各自的附表。 -
数据量:约 100,000 条数据,分别在主表和附表中填充数据。
一.建表语句
主表A
CREATE TABLE `test_a` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL,`description` varchar(255) DEFAULT NULL,`test_b_id` int DEFAULT NULL,`test_c_id` int DEFAULT NULL,`test_d_id` int DEFAULT NULL,`test_e_id` int DEFAULT NULL,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
附表b,c,d,e
CREATE TABLE `test_b` (`id` int NOT NULL AUTO_INCREMENT,`field_b1` varchar(255) DEFAULT NULL,`field_b2` int DEFAULT NULL,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=792843462 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `test_c` (`id` int NOT NULL AUTO_INCREMENT,`field_c1` varchar(255) DEFAULT NULL,`field_c2` datetime DEFAULT NULL,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100096 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `test_d` (`id` int NOT NULL AUTO_INCREMENT,`field_d1` text,`field_d2` tinyint(1) DEFAULT NULL,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100300 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `test_e` (`id` int NOT NULL AUTO_INCREMENT,`field_e1` int DEFAULT NULL,`field_e2` varchar(255) DEFAULT NULL,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=100444 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
二.填充数据
@SpringBootTest
class DemoTestQuerySpringbootApplicationTests {@Autowiredprivate TestAMapper testAMapper;@Autowiredprivate TestBMapper testBMapper;@Autowiredprivate TestCMapper testCMapper;@Autowiredprivate TestDMapper testDMapper;@Autowiredprivate TestEMapper testEMapper;@Testvoid contextLoads() {// 随机数生成器Random random = new Random();for (int i = 1; i <= 100000; i++) {// 插入 test_b 数据int testBId = insertTestB(random);// 插入 test_c 数据int testCId = insertTestC(random);// 插入 test_d 数据int testDId = insertTestD(random);// 插入 test_e 数据int testEId = insertTestE(random);// 插入 test_a 数据insertTestA(testBId, testCId, testDId, testEId, random);}}private int insertTestB(Random random) {TestB testB = new TestB();testB.setFieldB1("B Field " + random.nextInt(1000));testB.setFieldB2(random.nextInt(1000));testBMapper.insert(testB); // 插入数据return testB.getId(); }private int insertTestC(Random random) {TestC testC = new TestC();testC.setFieldC1("C Field " + random.nextInt(1000));testC.setFieldC2(new java.sql.Timestamp(System.currentTimeMillis()));testCMapper.insert(testC); // 插入数据return testC.getId(); }private int insertTestD(Random random) {TestD testD = new TestD();testD.setFieldD1("D Field " + random.nextInt(1000));testD.setFieldD2(random.nextBoolean());testDMapper.insert(testD); // 插入数据return testD.getId(); }private int insertTestE(Random random) {TestE testE = new TestE();testE.setFieldE1(random.nextInt(1000));testE.setFieldE2("E Field " + random.nextInt(1000));testEMapper.insert(testE); // 插入数据return testE.getId(); }private void insertTestA(int testBId, int testCId, int testDId, int testEId, Random random) {TestA testA = new TestA();testA.setName("Test A Name " + random.nextInt(1000));testA.setDescription("Test A Description " + random.nextInt(1000));testA.setTestBId(testBId);testA.setTestCId(testCId);testA.setTestDId(testDId);testA.setTestEId(testEId);testAMapper.insert(testA); // 插入数据}}
三.配置线程池
3.1配置
/*** 实现AsyncConfigurer接口* 并重写了 getAsyncExecutor方法,* 这个方法返回 myExecutor(),* Spring 默认会将 myExecutor 作为 @Async 方法的线程池。*/
@Configuration
@EnableAsync
public class ThreadPoolConfig implements AsyncConfigurer {/*** 项目共用线程池*/public static final String TEST_QUERY = "testQuery";@Overridepublic Executor getAsyncExecutor() {return myExecutor();}@Bean(TEST_QUERY)@Primarypublic ThreadPoolTaskExecutor myExecutor() {//spring的线程池ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//线程池优雅停机的关键executor.setWaitForTasksToCompleteOnShutdown(true);executor.setCorePoolSize(10);executor.setMaxPoolSize(10);executor.setQueueCapacity(200);executor.setThreadNamePrefix("my-executor-");//拒绝策略->满了调用线程执行,认为重要任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//自己就是一个线程工程executor.setThreadFactory(new MyThreadFactory(executor));executor.initialize();return executor;}}
3.2异常处理
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {private static final Logger log = LoggerFactory.getLogger(MyUncaughtExceptionHandler.class);@Overridepublic void uncaughtException(Thread t, Throwable e) {log.error("Exception in thread",e);}
}
3.3线程工厂
@AllArgsConstructor
public class MyThreadFactory implements ThreadFactory {private static final MyUncaughtExceptionHandler MyUncaughtExceptionHandler = new MyUncaughtExceptionHandler();private ThreadFactory original;@Overridepublic Thread newThread(Runnable r) {//执行Spring线程自己的创建逻辑Thread thread = original.newThread(r);//我们自己额外的逻辑thread.setUncaughtExceptionHandler(MyUncaughtExceptionHandler);return thread;}
}
四.Service查询方法
4.1left join连接查询
@Overridepublic IPage<TestAll> getTestAllPage_1(int current, int size) {// 创建 Page 对象,current 为当前页,size 为每页大小Page<TestAll> page = new Page<>(current, size);return testAMapper.selectAllWithPage(page);}
对应的xml 的sql语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.fth.demotestqueryspringboot.com.test.mapper.TestAMapper"><!-- 基本的 ResultMap 映射 --><resultMap id="BaseResultMap" type="org.fth.demotestqueryspringboot.com.test.entity.vo.TestAll"><id column="test_a_id" jdbcType="INTEGER" property="testAId" /><result column="name" jdbcType="VARCHAR" property="name" /><result column="description" jdbcType="VARCHAR" property="description" /><result column="test_b_id" jdbcType="INTEGER" property="testBId" /><result column="test_c_id" jdbcType="INTEGER" property="testCId" /><result column="test_d_id" jdbcType="INTEGER" property="testDId" /><result column="test_e_id" jdbcType="INTEGER" property="testEId" /><result column="created_at" jdbcType="TIMESTAMP" property="createdAt" /><result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" /><!-- TestB --><result column="field_b1" jdbcType="VARCHAR" property="fieldB1" /><result column="field_b2" jdbcType="INTEGER" property="fieldB2" /><result column="test_b_created_at" jdbcType="TIMESTAMP" property="testBCreatedAt" /><!-- TestC --><result column="field_c1" jdbcType="VARCHAR" property="fieldC1" /><result column="field_c2" jdbcType="TIMESTAMP" property="fieldC2" /><result column="test_c_created_at" jdbcType="TIMESTAMP" property="testCCreatedAt" /><!-- TestD --><result column="field_d1" jdbcType="VARCHAR" property="fieldD1" /><result column="field_d2" jdbcType="BOOLEAN" property="fieldD2" /><result column="test_d_created_at" jdbcType="TIMESTAMP" property="testDCreatedAt" /><!-- TestE --><result column="field_e1" jdbcType="INTEGER" property="fieldE1" /><result column="field_e2" jdbcType="VARCHAR" property="fieldE2" /><result column="test_e_created_at" jdbcType="TIMESTAMP" property="testECreatedAt" /></resultMap><!-- 分页查询 TestA 和其他表的数据 --><select id="selectAllWithPage" resultMap="BaseResultMap">SELECTa.id AS test_a_id,a.name,a.description,a.test_b_id,a.test_c_id,a.test_d_id,a.test_e_id,a.created_at,a.updated_at,-- TestBb.field_b1,b.field_b2,b.created_at AS test_b_created_at,-- TestCc.field_c1,c.field_c2,c.created_at AS test_c_created_at,-- TestDd.field_d1,d.field_d2,d.created_at AS test_d_created_at,-- TestEe.field_e1,e.field_e2,e.created_at AS test_e_created_atFROM test_a aLEFT JOIN test_b b ON a.test_b_id = b.idLEFT JOIN test_c c ON a.test_c_id = c.idLEFT JOIN test_d d ON a.test_d_id = d.idLEFT JOIN test_e e ON a.test_e_id = e.id</select></mapper>
4.2多线程查询
@Overridepublic IPage<TestAll> getTestAllPage_2(int current, int size) {IPage<TestA> testAPage = testAMapper.selectPage(new Page<>(current, size), null);List<TestA> testAS = testAPage.getRecords();CompletableFuture<List<TestB>> futureBs = selectTestBids(testAS.stream().map(TestA::getTestBId).collect(Collectors.toSet()));CompletableFuture<List<TestC>> futureCs = selectTestCids(testAS.stream().map(TestA::getTestCId).collect(Collectors.toSet()));CompletableFuture<List<TestD>> futureDs = selectTestDids(testAS.stream().map(TestA::getTestDId).collect(Collectors.toSet()));CompletableFuture<List<TestE>> futureEs = selectTestEids(testAS.stream().map(TestA::getTestEId).collect(Collectors.toSet()));// 等待所有异步任务完成并收集结果CompletableFuture<Void> allFutures = CompletableFuture.allOf(futureBs, futureCs, futureDs, futureEs);try {// 等待所有异步任务完成allFutures.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();throw new RuntimeException("Failed to fetch data", e);}// 获取异步查询的结果List<TestB> bs = futureBs.join();List<TestC> cs = futureCs.join();List<TestD> ds = futureDs.join();List<TestE> es = futureEs.join();// 将结果映射到Map以便快速查找Map<Integer, TestB> bMap = bs.stream().collect(Collectors.toMap(TestB::getId, b -> b));Map<Integer, TestC> cMap = cs.stream().collect(Collectors.toMap(TestC::getId, c -> c));Map<Integer, TestD> dMap = ds.stream().collect(Collectors.toMap(TestD::getId, d -> d));Map<Integer, TestE> eMap = es.stream().collect(Collectors.toMap(TestE::getId, e -> e));List<TestAll> testAllList = testAS.stream().map(testA -> {TestAll testAll = new TestAll();testAll.setTestAId(testA.getId());testAll.setName(testA.getName());testAll.setDescription(testA.getDescription());testAll.setCreatedAt(testA.getCreatedAt());// 根据 testBId 填充 TestB 的字段if (testA.getTestBId() != null) {TestB testB = bMap.get(testA.getTestBId());if (testB != null) {testAll.setFieldB1(testB.getFieldB1());testAll.setFieldB2(testB.getFieldB2());testAll.setTestBCreatedAt(testB.getCreatedAt());}}// 根据 testCId 填充 TestC 的字段if (testA.getTestCId() != null) {TestC testC = cMap.get(testA.getTestCId());if (testC != null) {testAll.setFieldC1(testC.getFieldC1());testAll.setFieldC2(testC.getFieldC2());testAll.setTestCCreatedAt(testC.getCreatedAt());}}// 根据 testDId 填充 TestD 的字段if (testA.getTestDId() != null) {TestD testD = dMap.get(testA.getTestDId());if (testD != null) {testAll.setFieldD1(testD.getFieldD1());testAll.setFieldD2(testD.getFieldD2());testAll.setTestDCreatedAt(testD.getCreatedAt());}}// 根据 testEId 填充 TestE 的字段if (testA.getTestEId() != null) {TestE testE = eMap.get(testA.getTestEId());if (testE != null) {testAll.setFieldE1(testE.getFieldE1());testAll.setFieldE2(testE.getFieldE2());testAll.setTestECreatedAt(testE.getCreatedAt());}}return testAll;}).collect(Collectors.toList());// 创建并返回新的分页对象IPage<TestAll> page = new Page<>(testAPage.getCurrent(), testAPage.getSize(), testAPage.getTotal());page.setRecords(testAllList);return page;}@Asyncpublic CompletableFuture<List<TestB>> selectTestBids(Set<Integer> bids) {return CompletableFuture.supplyAsync(() -> testBMapper.selectBatchIds(bids));}@Asyncpublic CompletableFuture<List<TestC>> selectTestCids(Set<Integer> cids) {return CompletableFuture.supplyAsync(() -> testCMapper.selectBatchIds(cids));}@Asyncpublic CompletableFuture<List<TestD>> selectTestDids(Set<Integer> dids) {return CompletableFuture.supplyAsync(() -> testDMapper.selectBatchIds(dids));}@Asyncpublic CompletableFuture<List<TestE>> selectTestEids(Set<Integer> eids) {return CompletableFuture.supplyAsync(() -> testEMapper.selectBatchIds(eids));}
五.结果测试
5.1连接查询
查询结果表格
current | size | 响应时间 |
---|---|---|
1 | 20 | 16ms |
50 | 20 | 23ms |
100 | 20 | 22ms |
500 | 20 | 52ms |
200 | 200 | 213ms |
500 | 200 | 517ms |
5.2多线程查询
查询结果表格
current | size | 响应时间 |
---|---|---|
1 | 20 | 18ms |
50 | 20 | 17ms |
100 | 20 | 17ms |
500 | 20 | 21ms |
200 | 200 | 56ms |
500 | 200 | 80ms |
总结与建议
- 选择联表查询:当数据量较小,或者查询逻辑较为简单时,使用联表查询可以更简单直接,查询性能也较为优秀。
- 选择多线程查询:当面对大数据量或者复杂查询时,采用多线程查询将带来更显著的性能提升。通过异步并行查询,可以有效缩短响应时间,提升系统的整体性能。
在实际开发中,可以根据具体的业务需求和数据库的规模,合理选择查询方式,从而提高数据库查询效率,优化系统性能
相关文章:

Spring Boot + MySQL 多线程查询与联表查询性能对比分析
Spring Boot MySQL: 多线程查询与联表查询性能对比分析 背景 在现代 Web 应用开发中,数据库性能是影响系统响应时间和用户体验的关键因素之一。随着业务需求的不断增长,单表查询和联表查询的效率问题日益凸显。特别是在 Spring Boot 项目中࿰…...

Java 设计模式~工厂模式
在java开发,工厂模式应用场景有哪些?在Spring boot原码中 有哪些工厂类,并做相应的代码介绍。 工厂模式 工厂模式(Factory Pattern)是Java中一种常用的创建型设计模式,它提供了一种创建对象的最佳方式。此…...

OmicsTools生信环境全自动化安装配置教程,代做生信分析和辅导
OmicsTools软件介绍和下载安装配置 软件介绍 我开发了一款本地电脑无限使用的零代码生信数据分析作软图神器电脑软件OmicsTools,旨在成为可以做各种医学生物生信领域科研数据分析作图的的全能科研软件,欢迎大家使用OmicsTools进行生物医学科研数据分析…...

鸿蒙HarmonyOS应用开发 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
鸿蒙心路旅程:探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力 HarmonyOS Next 是华为推出的全新一代操作系统,旨在进一步推动分布式技术的深度应用和生态融合。本文将从技术特点、应用场景入手,通过实战案例与代码示例&…...

二分模板题
题目传送门 主要思路: 暴力会tle n的3次方了然后 二分可以找中间然后去二分枚举两边 最后结果 ansa小于它的数*c大于它的数 注意要判断是否符合条件 即如果a的小于它的数还大于它就不成立 或者c的数小于它也不成立结果 要注意转long long ans(long long)tp1*tp2; …...

一篇文章掌握Git的基本原理与使用
目录 一、创建仓库 1.1 git init 1.2 git clone 二、工作区域与文件状态 三、添加和提交文件 3.1 git status 3.2 git add git rm --cached 3.3 git commit git log 四、版本回退 soft hard mixed 总结 五、查看差异 工作区与暂存区 工作区与本地仓库 暂存区…...

「Mac畅玩鸿蒙与硬件43」UI互动应用篇20 - 闪烁按钮效果
本篇将带你实现一个带有闪烁动画的按钮交互效果。通过动态改变按钮颜色,用户可以在视觉上感受到按钮的闪烁效果,提升界面互动体验。 关键词 UI互动应用闪烁动画动态按钮状态管理用户交互 一、功能说明 闪烁按钮效果应用实现了一个动态交互功能…...

朗新科技集团如何用云消息队列 RocketMQ 版“快、准、狠”破解业务难题?
作者:邹星宇、刘尧 朗新科技集团:让数字化的世界更美好 朗新科技集团股份有限公司是领先的能源科技企业,长期深耕电力能源领域,通过新一代数字化、人工智能、物联网、电力电子技术等新质生产力,服务城市、产业、生活中…...

【Ubuntu】Ubuntu的Desktop(学习/用户使用)和Bit版本(工作)
这篇文章似乎没什么必要写,但想了想还是决定记录一下,也许对新手入坑Ubuntu会有帮助, 事实上也很简单,一个是桌面版本,另一个是字符界面版本。 桌面版:拥有图形桌面 字符界面,易上手ÿ…...

cmake CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_LIST_DIR的区别
在 CMake 中,CMAKE_CURRENT_LIST_DIR 和 CMAKE_CURRENT_SOURCE_DIR 都是指代当前 CMake 文件所在的路径,但它们的含义和用途有所不同: CMAKE_CURRENT_LIST_DIR: 表示 当前处理的 CMake 文件(例如 CMakeLists.txt&#…...

学会用VSCode debug
本文主要介绍了 VS Code 的调试功能,包括其强大的内置调试器,支持多种语言,如 JavaScript、TypeScript 等。通过简单项目示例展示调试过程,还介绍了运行面板和菜单、启动配置、调试操作、断点、记录点等功能,以及三种调…...

C语言专题之结构体的使用
结构体(struct)是一种用户自定义的数据类型,它允许将不同类型的数据组合在一起,形成一个新的数据类型。结构体在编程中非常常见,尤其是在需要处理复杂数据结构的情况下。以下是结构体的基本使用方法: 一、结…...

python中的高阶函数
1、什么是高阶函数? 高阶函数是指将函数作为参数传入。就是高阶函数 2、高阶函数有哪些? map 映射函数 >>> print(list(map(lambda x:x*x,range(1,11)))) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] >>> print(list(map(lambda x:st…...

学习笔记063——通过使用 aspose-words 将 Word 转 PDF 时,遇到的字体改变以及乱码问题
文章目录 1、问题描述:2、解决方法: 1、问题描述: Java项目中,有个需要将word转pdf的需求。本人通过使用aspose-words来转换的。在Windows中,转换是完全正常的。但是当部署到服务器时,会出现转换生成的pdf…...

SpringBoot整合Mockito进行单元测试超全详细教程 JUnit断言 Mockito 单元测试
Mock概念 Mock叫做模拟对象,即用来模拟未被实现的对象可以预先定义这个对象在特定调用时的行为(例如返回值或抛出异常),从而模拟不同的系统状态。 导入Mock依赖 pom文件中引入springboot测试依赖,spring-boot-start…...

【AI知识】过拟合、欠拟合和正则
一句话总结: 过拟合和欠拟合是机器学习中的两个相对的概念,正则化是用于解决过拟合的方法。 1. 欠拟合: 指模型在训练数据上表现不佳,不能充分捕捉数据的潜在规律,导致在训练集和测试集上的误差都很高。欠拟合意味着模…...

MacOS编译webRTC源码小tip
简单记录一下,本人在编译webRTC时,碰到了一下比较烦人的问题,在MacOS终端下,搭建科学上网之后,chromium的depot_tools仓库成功拉下来了,紧接着,使用fetch以及gclient sync始终都返回curl相关的网…...

Linux基础命令(三):文件压缩及解压缩命令
文件压缩及解压缩命令 tar — 打包和压缩 tar 是一个用于打包文件的工具,常常用来将多个文件或目录打包成一个单独的文件。它本身不进行压缩,但可以与压缩工具(如 gzip 或 bzip2)一起使用。 用法: 打包文件࿰…...

目标跟踪算法:ByteTrack、卡尔曼滤波、匈牙利算法、高置信度检测目标、低置信度检测目标
目录 1 ByteTrack特点 2 ByteTrack和SORT区别----个人通俗理解 3 ByteTrack算法原理 4 ByteTrack整体流程图 上一篇博客我复习了下SORT跟踪算法,这一篇博客我再复习下ByteTrack跟踪算法,ByteTrack里面也是用了卡尔曼滤波和匈牙利算法&#x…...

[定昌linux系统]如何安装jdk8
1:下载jdk8 的 arm64 的版本,由于官方下载需要gmail,我的gmail 密码忘了,所以从csdn上下载了一份,地址: https://download.csdn.net/download/qq_27742163/88533548?utm_mediumdistribute.pc_relevant_download.none…...

【Cadence32】PCB多层板电源、地平面层创建心得➕CM约束管理器Analyze分析显示设置➕“DP”报错DRC
【转载】Cadence Design Entry HDL 使用教程 【Cadence01】Cadence PCB Edit相对延迟与绝对延迟的显示问题 【Cadence02】Allegro引脚焊盘Pin设置为透明 【Cadence03】cadence不小心删掉钢网层怎么办? 【Cadence04】一般情况下Allegro PCB设计时的约束规则设置&a…...

基于SpringBoot+Vue的新闻管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 随着互联网技术的飞速发展,信息传播速度不断加快,新闻媒体行业面临着巨大的机遇与挑战。传统的新闻媒体正在逐渐向数字化转型,而新闻管理系统作为数字化新闻媒体的核心组成部分,其…...
图的割点、割边(Tarjan算法)
深度优先搜索的利用。 在一个无向连通图中,如果删掉某个顶点后,图不再连通(即任意两点之间不能互相到达),我们称这样的顶点为割点。 在一个无向连通图中,如果删掉某条边后,图不在连通࿰…...

算法学习(十四)—— 二叉树的深度搜索(DFS)
目录 关于dfs 部分OJ题详解 2331. 计算布尔二叉树的值 129. 求根节点到叶节点数字之和 814. 二叉树剪枝 98. 验证二叉搜索树 230. 二叉搜索树中第K小的元素 257. 二叉树的所有路径 关于dfs 算法学习(十二)—— 递归,搜索,…...

【vue2】封装自定义的日历组件(三)之基础添加月份的加减定位到最新月份的第一天
我们在切换月份的时候,希望高亮显示在每个月的第一天上面,这样的效果我们要怎么来实现,其实也很简单,我们先看下实现的效果 实现效果 代码实现 原理就是获取到每月的第一天日期,然后再跟整个的数据进行对比ÿ…...

LabVIEW偏心圆筒流变仪测控系统
偏心圆筒流变仪是一种专门研究聚合物熔体在复杂流场中特殊流变行为的先进设备。通过结合硬件控制与LabVIEW软件开发,本系统实现了对流变仪功能的精准控制与数据采集,进一步提高了聚合物加工过程的研究精度和效率。 项目背景 传统的流变测量设备多集中于…...

Runloop
假设你的项目中有关tableView,然后还有一个定时器timer在执行,定时器代码如下: var num 0override func viewDidLoad() {super.viewDidLoad()let timer Timer(timeInterval: 1,target: self,selector: #selector(self.run),userInfo: nil,r…...

SpringBoot的Bean类三种注入方式(附带LomBok注入)
SpringBoot的Bean类三种注入方式(附带LomBok注入) 在 Spring Boot 中,Bean 的注入方式主要包括构造函数注入(Constructor Injection)、字段注入(Field Injection)以及 Setter 方法注入…...

开源向量数据库介绍说明
开源向量数据库 Milvus 特点:分布式、高性能,支持亿级向量检索。 支持的数据类型:文本、图像、音频、视频等。 使用场景:推荐系统、语义搜索、图像搜索。 数据存储后端:支持多种后端,如 SQLite、MySQL、Pos…...

【前端】深度解析 JavaScript 中的 new 关键字与构造函数
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 💯前言💯构造函数的核心特性💯new 关键字的执行机制💯实例代码与详细解析代码示例代码逐步解析 💯new 的内部执行模拟执行过程的详细解析 &am…...