自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(38)
  • 收藏
  • 关注

原创 二叉树层序遍历详解:从原理到代码实现

层序遍历(Level Order Traversal),顾名思义,是 “按层遍历”—— 先访问二叉树的第 1 层(根节点),再访问第 2 层的所有节点,接着访问第 3 层,直到最后一层。1 (第1层)/ \2 3 (第2层)/ \ \4 5 6 (第3层)它的层序遍历结果是:1 → 2 → 3 → 4 → 5 → 6。如果要求 “分层输出”(即把每一层的节点单独存为一个列表),结果则是:[[1], [2, 3], [4, 5, 6]],这种形式在面试题中更常见。// 二叉树节点类。

2025-09-23 11:46:02 885

原创 二叉树的前序、中序、后序遍历

三种遍历的核心差异是 “根节点的访问时机”,左、右子树的遍历顺序始终是 “先左后右”;递归实现的通用框架:初始化集合→递归遍历→集合转数组,仅需调整 “根节点加入集合的位置”;递归的底层是 JVM 的方法栈,通过栈帧的入栈 / 出栈实现 “回到上一个节点”;实际开发中,若树深度较小,优先选择递归(简洁);若树深度较大,需用迭代法(避免栈溢出)。掌握二叉树的递归遍历,是理解二叉树其他操作的基础,建议结合实例手动模拟栈帧变化,彻底吃透递归逻辑。

2025-09-22 19:04:56 1481

原创 MQTT协议的理解与实践

MQTT 是由 IBM 在 1999 年设计的一种基于 TCP/IP 的轻量级发布 / 订阅消息协议,最初用于解决石油钻井平台与陆地服务器之间的低带宽、高延迟、不稳定网络下的通信问题。硬件资源有限:如嵌入式设备(传感器、单片机),内存和 CPU 性能较低;网络条件恶劣:如低带宽、高丢包率、高延迟(如卫星通信、偏远地区物联网设备)。与 HTTP、AMQP 等协议相比,MQTT 的协议头最小仅 2 字节,能极大减少网络传输开销,因此广泛应用于物联网、智能家居、工业控制、车联网等场景。

2025-09-19 15:12:16 987

原创 深入理解 Java 中的守护线程与用户线程

要区分守护线程和用户线程,首先需要明确它们在程序中的核心定位 —— 前者是 “服务者”,后者是 “任务本身”。在开发中,选择守护线程还是用户线程,核心取决于任务是否需要 “完整执行”若任务是核心业务逻辑(如订单处理、数据计算、文件上传等),必须保证执行完毕,否则会导致业务中断或数据异常,应使用用户线程;若任务是后台辅助服务(如日志记录、垃圾回收、资源监控等),可随时中断,不影响核心业务,应使用守护线程。用户线程 “做主”,守护线程 “服务”,二者协同工作,共同支撑 Java 程序的高效运行。

2025-09-18 17:48:26 817

原创 常见的排序算法

排序算法平均时间复杂度最坏时间复杂度空间复杂度稳定性原地排序适用场景冒泡排序O(n²)O(n²)O(1)稳定是小规模数据选择排序O(n²)O(n²)O(1)不稳定是小规模数据,交换成本高的场景插入排序O(n²)O(n²)O(1)稳定是小规模或部分有序数据快速排序O(n log n)O(n²)O(log n)不稳定是大规模数据,通用场景归并排序O(n log n)O(n log n)O(n)稳定否大规模数据,需稳定性场景。

2025-09-17 21:04:42 1048

原创 深入解析 HTTP 状态码

状态码代码名称所属类别核心说明100Continue1xx 信息性状态码服务器已接收请求头,告知客户端可继续发送请求体,常用于文件上传等场景避免资源浪费1011xx 信息性状态码服务器同意按客户端请求切换协议(如 HTTP 转 WebSocket),支持实时双向通信200OK2xx 成功状态码最常见成功码,服务器已成功处理请求并返回对应资源或结果,适用于多数 GET、POST 等请求201Created2xx 成功状态码。

2025-09-17 17:41:48 802

原创 如何判断链表中有环——快慢指针法

慢指针最多走 “链表长度 n” 步(进入环后最多再走 1 个环的长度),快指针走的步数是慢指针的 2 倍,整体时间复杂度仍是 O (n),和 “快指针走 3 步” 的 O (n) 一致,但实际执行时步数更少,效率更高。这种情况下,无论环的大小是多少、初始间隔是多少,快指针都不会 “错过” 慢指针 —— 每一轮都能缩小 1 步的距离,直到追上(就像两个人在环形跑道上,快的人每次比慢的人多跑 1 米,早晚会追上)。快慢指针实际上指的是两个指针,一个指针向后走一步,一个指针向后走两步,判断给定的链表中是否有环。

2025-09-16 15:20:10 923

原创 有关合并两个有序链表的解答

设置虚拟节点的头节点为0,两个链表进行对比后,添加在虚拟节点后面,最后返回的是虚拟节点的后继(return dummy.next),最后呈现的链表如下图所示。我们需要创建一个虚拟节点,主要是用于简化代码逻辑,避免处理头节点的特殊情况。数据范围: 0≤n≤10000≤n≤1000,−1000≤节点值≤1000−1000≤节点值≤1000。输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

2025-09-16 14:03:57 355

原创 有关反转链表题目的详细解答

它就完成了链表反转,所以,循环条件是"

2025-09-15 23:35:57 617

原创 深入理解链表:从基础概念到经典算法

链表是一种常见的线性数据结构,它通过节点之间的引用(或指针)连接形成链式结构。与数组不同,链表中的元素在内存中不是连续存储的,这使得链表在插入和删除操作上具有独特的优势。想象一下日常生活中的锁链:每一环(节点)都包含了具体内容(数据)和与另一环的连接(指针),这就是链表的直观体现。链表是一种灵活高效的数据结构,掌握链表的操作是理解更复杂数据结构和算法的基础。理解节点之间的引用关系掌握指针操作的技巧注意处理边界条件(空链表、单节点链表等)学会利用快慢指针等特殊技巧解决问题。

2025-09-15 19:29:04 825

原创 Java 中 ArrayList 扩容机制的深度解析

底层基础:基于Object[]数组实现,通过动态扩容实现 “容量自适应”,size记录元素实际个数,elementData.length表示数组容量;初始容量:无参构造器在 JDK 1.8 及之后采用懒加载(初始容量 0,首次添加元素时设为 10),指定容量构造器可直接设定初始容量;触发条件:添加元素时,若所需最小容量(size + 1)超过当前数组容量,触发扩容;核心逻辑:默认按 1.5 倍扩容,通过两次校验确保新容量合理,最终通过数组复制完成扩容;优化方法。

2025-09-15 12:13:08 970

原创 MySQL锁机制深度解析

锁粒度加锁效率并发性能死锁概率支持存储引擎适用场景表锁高低低读多写少、批量操作行锁低高高InnoDB高并发读写混合、精准操作页锁中中中BDB(几乎淘汰)数据量大、索引设计困难(极少)掌握 MySQL 锁的核心是 “按需选择”,没有绝对最优的锁,只有最适合业务场景的锁。优先选 InnoDB 行锁:在支持事务和高并发的场景下,行锁是平衡性能与一致性的最佳选择,但需确保查询使用索引(避免行锁退化表锁)。读多写少用表锁。

2025-09-14 00:14:15 660

原创 Elasticsearch的理解与使用

在大数据与云计算时代,“高效检索” 与 “实时分析” 成为业务突破的关键能力。Elasticsearch(简称 ES)作为一款开源分布式搜索与分析引擎,凭借其的特性,已成为日志分析、全文检索、业务监控等场景的 “标配工具”。本文将从 ES 的核心本质出发,深入剖析其架构原理,再通过完整的 Java 代码实现核心功能,帮助开发者从 “认知” 到 “落地” 全面掌握 ES。

2025-09-12 18:01:26 1309

原创 索引的优化与失效

B+Tree是B-Tree的变种,在非叶子节点只存储键值,在叶子节点存储数据和指针,这样减少了树的高度,提高了查询效率。索引本质上是一种数据结构,它类似于书籍的目录,能够帮助数据库系统快速定位到所需的数据,而无需扫描整个表。复合索引遵循最左前缀原则,即查询必须使用索引的最左列才能利用索引。覆盖索引是指索引包含了查询所需的所有字段,这样查询可以直接从索引中获取数据,而无需回表查询数据行。将最常用于查询条件的列放在索引的前面,同时考虑列的选择性,将高选择性的列放在前面可以更有效地过滤数据。

2025-09-12 15:38:31 776

原创 MySQL的常用命令

【代码】MySQL的常用命令。

2025-09-11 11:56:21 485

原创 Linux常用命令大全

Linux作为最流行的服务器操作系统,其命令行工具是每个开发者和管理员必须掌握的技能。

2025-09-10 17:20:57 348

原创 CAS和AQS的理解与区别

CAS(Compare-And-Swap),中文意思是比较并交换,是一种硬件级别的原子操作。// 注意:这是一个原子操作,不会被中断内存位置(V)、预期原值(A)、新值(B)。当且仅当内存位置V的值等于预期原值A时,处理器才会将该位置更新为新值B,否则不执行任何操作。无论哪种情况,都会返回该位置原来的值。AQS 是JUC 并发包的核心基础框架,是一个用于构建锁和同步器(Synchronizer)的抽象框架。SemaphoreThreadPoolExecutor 中的 Worker核心思想。

2025-09-10 10:11:01 600

原创 TCP的三次握手和四次挥手

TCP 是面向连接、可靠的协议。在传输数据之前,双方必须先建立一条稳定的连接通道;数据传输完毕后,则需要优雅地关闭连接,以释放系统资源。这就是“握手”和“挥手”的目的。用来标识发送的数据字节流,解决网络包乱序问题。告诉对方下一次期望收到的序列号,确认此前的数据已收到,解决丢包问题。用于建立连接(Synchronize)。确认标识,确认收到数据。用于断开连接(Finish)。三次握手四次挥手。

2025-09-09 20:18:20 1027

原创 Spring Security的理解与使用

Entity@Id@Entity@Id@ManyToMany(fetch = FetchType.EAGER) // 急加载,获取用户时立刻获取角色密码必须编码:永远不要用明文存储密码。是当前的首选。最小权限原则:只授予用户完成其工作所必需的最小权限。纵深防御:不要只依赖 Spring Security。在服务层方法上也可以使用注解进行二次校验。保持更新:Spring Security 本身和其依赖库可能会发现漏洞,定期更新版本。

2025-09-09 19:21:50 582

原创 JWT全面理解

JWT 的本质是一串经过加密签名的 JSON 格式字符串,用于在客户端和服务器之间安全地传递 “声明”(Claims,即用户身份、权限等信息)。分布式系统中服务间通信(如微服务 A 向微服务 B 传递用户权限信息)、跨组织数据交换(如第三方登录后,平台间传递用户基本信息)。(如 role: admin、permissions: ["read", "write"]),服务器验证 JWT 后,直接。减少数据库查询次数(验证身份时无需查库),提升系统性能。服务器不存储任何会话信息,仅通过 JWT 验证身份。

2025-09-09 18:05:03 1444

原创 注册中心宕机,远程调用还能成功吗?

我们先来简单回顾一下注册中心是干嘛的。在微服务架构中,服务之间的调用不像以前那样直接写死IP和端口,而是通过注册中心(比如Nacos、Eureka、Zookeeper)来动态发现服务。举个例子:订单服务要调用用户服务,它不会直接写死用户服务的地址,而是去注册中心问:“用户服务在哪?”注册中心回答:“在192.168.1.10:8080。”订单服务这才发起调用。所以,注册中心就像一个服务电话本,负责服务的注册与发现。注册中心宕机后,短期内远程调用可能仍然成功,因为客户端有本地缓存和服务长连接。

2025-09-09 12:17:13 429

原创 Spring Boot注解

指定 Spring 扫描组件(@Component、@Service、@Controller 等)的包路径。若不指定,默认扫描当前类所在包及子包。// ...标记一个类为配置类,作用类似于传统 Spring 中的 XML 配置文件。在配置类中,可通过@Bean 注解定义 Bean。示例:自定义 RedisTemplate Bean@Bean// 配置序列化规则...

2025-09-05 10:41:42 897

原创 Shiro的理解

实现@Autowired// 授权:查询用户的角色和权限@Override// 从数据库查询用户的角色、权限// 添加角色// 添加权限// 认证:查询用户信息(账号、密码)@Override// 从数据库查询用户throw new UnknownAccountException("账号不存在");// 返回认证信息(账号、密码、盐、Realm名称)username,getName()若默认过滤器不够用(如自定义权限逻辑、记录操作日志),可写。

2025-09-04 10:12:59 724

原创 Redis 核心知识体系与面试考点

你可以把它理解为 “超级内存哈希表”:不仅能快速存取值,还支持丰富的数据结构(如列表、集合)和高级功能(如持久化、分布式锁)。分布式系统中,多服务抢同一资源(如库存)时,需要 “分布式锁” 保证 “同一时间只有一个服务能操作”。(避免线程切换、锁竞争的开销,保证高效);:查询 “Redis 和数据库都不存在的 Key”,每次请求都直击数据库,导致数据库压力暴增(常由黑客恶意构造请求引发)。:某个 “热点 Key”(如秒杀商品)在 Redis 中过期,短时间内大量请求打到数据库,导致数据库压力骤增甚至崩溃。

2025-09-03 12:12:20 724

原创 SpringBoot自动配置的原理

触发点:@SpringBootApplication中的@EnableAutoConfiguration开启自动配置。候选配置:通过META-INF/spring.factories加载所有可能的自动配置类。条件过滤:通过@Conditional注解筛选出符合当前项目环境(依赖、配置、容器状态)的自动配置类。注册组件:生效的自动配置类通过@Bean注册所需组件,并通过@ConfigurationProperties绑定外部配置。用户优先:用户自定义的 Bean 或配置会覆盖自动配置的默认值。

2025-08-24 14:02:03 1053

原创 Spring Bean生命周期全解析

bean的生命周期是什么,应该怎么理解Spring Bean 的生命周期是指从 Bean 定义被加载到容器中,到 Bean 实例被创建、初始化,最终被销毁的完整过程。首先,在定义阶段,spring容器通过 XML 配置、注解(如 @Component、@Bean)或 API 方式,解析 Bean 的元数据,封装为 BeanDefinition 对象,存储在 BeanDefinitionRegistry 中。

2025-08-17 11:24:38 1184

原创 MyBatis中的Mapper接口和Executor组件的理解

核心逻辑:二级缓存是 “跨 SqlSession” 的缓存,由CachingExecutor(装饰器模式)代理具体 Executor(如SimpleExecutor)实现,缓存数据存储在Cache对象中(默认是PerpetualCache,本质也是 Map),且按Mapper接口隔离(每个 Mapper 有自己的缓存)。Mapper 是 “请求入口”(封装业务调用),Executor 是 “执行核心”(处理 SQL 交互),二者通过MappedStatement衔接,完成从方法调用到数据库操作的全流程。

2025-08-10 22:48:25 1211

原创 线程池的状态

TIDYING 是过渡状态,仅在所有任务和线程终止后短暂存在,用于执行自定义清理逻辑(通过重写 terminated() 方法)。该状态的线程池,不会接收新任务,也不会处理工作队列中的任务,同时会中断正在运行的任务;该状态表明所有的任务已经终止,工作线程的数量为0,即将调用terminated( );如果工作队列为空,并且线程池中执行的任务也为空,线程池进入TIDYING状态;该状态的线程池,不会接收新任务,但是会继续处理工作队列中的任务;该状态的线程池会接收新任务,并处理阻塞队列中的任务;

2025-08-10 19:49:58 230

原创 线程常用的方法

join()方法是指线程的插队。当前线程暂停执行,直到调用join()方法的线程执行完毕,此外,不影响其它线程的运行。以下就是一个案例当t1线程插队时,就先执行t1,然后再执行主线程,所以输出结果为。

2025-08-10 19:36:54 766

原创 JUC并发集合

当我们往一个集合容器中写入元素时(添加、修改、删除),并不会直接在集合容器中写入,而是先将当前集合容器进行Copy,复制。添加新元素至集合时,会将当前数组Copy复制新数组,并将新元素添加至新数组,最后替换原数组。执行过程中,使用ReentrantLock加锁。根据指定下标,到原数组中读取元素。读取过程中不加锁,允许多个线程并发读取。删除指定下标元素。根据指定下标,从原数组中,Copy复制其它元素至新数组,最后替换原数组。通过 CopyOnWriteArrayList 存储元素,添加元素时检查是否已存在(使

2025-08-10 19:35:32 640

原创 谈谈对于CAS的理解

在高并发的业务场景下,线程安全可以通过synchronized或Lock来保证同步,从而达到线程安全的目的。但是,synchronized或Lock都是基于互斥锁的思想实现,加锁和释放锁的过程中,都会带来性能损耗问题。此外,还有通过JUC提供的CAS机制,实现一种无锁的非阻塞线程同步方式,保证线程安全。

2025-07-21 19:27:15 842

原创 有关线程池的核心配置参数及流程

线程池是用于管理和复用线程的一种技术,可以优化线程的执行效率。因为,频繁创建和销毁线程,会带来额外的系统开销,而线程池可以通过创建并重用一组线程来执行任务,可以显著减少这种开销,提高程序的性能和响应能力。

2025-07-21 17:56:56 1016

原创 多线程同步并发(synchronized和ReentrantLock)

简单来说,使用 Synchronized 关键字将一段代码逻辑,用一把锁给锁起来,只有获得了这把锁的线程才访问。并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住的代码,从而确保代码的线程安全。例如,'+','-','='等这些算数运算符不具有原子性,会被别的进程打断。synchronized (counter.object){//加锁。//让数字线程等待 并释放锁。//同步锁 可以放在外面 也可以放在里面。//创建ReentrantLock锁对象。

2025-07-16 21:51:57 844

原创 synchronized进阶

对于一些锁竞争的场景,可以通过设置参数(-XX:-UseBiasedLocking),禁用偏向锁,直接使用轻量级锁,目的时为了减少启动初期的锁升级开销。//输出结果是一样的。:当一个线程,首次访问同步代码块并获取锁时,会在对象头的 Mark Word 中存入该线程 ID。在单线程环境下,锁会偏向于第一个获取该锁的线程,后续该线程再次获取锁时不用竞争。,GC进行垃圾回收,并将锁的状态,标记为不再使用,JVM会将锁状态为无锁。当有另一个线程,尝试访问同一同步块时,偏向锁会升级为轻量级锁。

2025-07-16 18:57:15 592

原创 Integer缓存池

定义了一个内部类IntegerCache通过final关键字定义了缓存池的最小值low为-128通过final关键字定义了缓存池的最大值,未设置初始值通过final关键字定义了一个Integer类型的数组,用来存储缓存的Integer对象。

2025-02-10 11:02:27 850

原创 StringBuilder类的数据结构和扩容方式解读

StringBuilder初始化分为无参方法定义和有参方法定义,用无参方法定义时,默认数组的长度为16,以下是无参定义和有参定义的StringBuilder和有关的方法无参定义和有参定义输出结果当然在初始化时,我们也可以直接定义字符串的内容如下此时输出结果为16+字符的长度有关可变字符串的一部分方法。

2025-01-30 22:30:29 581

原创 String类的equals()的作用和源代码解读

我们通过阅读String源码中有关equals()方法的定义,可以得知这个方法是用来比较字符串是否相等,返回值是一个布尔类型的值,下面我们对这部分源码做一个解释。首先,我们先通过”==“判断,传入的值与目标值的内存地址是否相等,当内存地址相同时,就代表两个对象的内容也一定相同。在这里我们要了解到,equals()方法默认的是比较内存地址,而String源码中对这个方法进行重写,当判断内存地址相同时,返回值为”true“。

2025-01-21 20:25:02 331

原创 String为什么是不可变的?

所以String的数据结构是不可变的,它主要用来存储一些字符(char)或者一些整数(int)的哈希码值,那么它的优点是使得字符串的访问和操作(如字符查找、子字符串提取等)非常高效,支持高效的随机访问,同时不可变性使得字符串在作为参数传递时不会被意外修改,从而增强了程序的安全性。在原字符串的基础上无法进行拼接,必须创建一个新的字符串对象完成拼接,在s1的基础上进行拼接,此时系统会报错,那么想要完成一个字符串的拼接,就需要创建一个新的字符串。来存储字符串的内容。

2025-01-21 16:11:13 252 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除