- 博客(31)
- 收藏
- 关注
原创 思考:客户端负载均衡和服务器负载均衡有什么区别?
负载均衡没有 “绝对最好” 的方案,只有 “最合适” 的场景。如果是微服务内部服务间调用,优先用客户端负载均衡(Spring Cloud LoadBalancer),快、灵活、无单点。如果是外部请求接入微服务,优先用服务端负载均衡(Nginx),好管理、能防护、对客户端友好。复杂项目就两者结合,外部 Nginx 扛入口,内部 LoadBalancer 提效率,这样的架构既稳定又高效。
2025-09-20 16:31:38
1086
1
原创 Java 集合框架 Set 接口:实现类的底层数据结构与核心特点
Set 接口继承自 Collection 接口,其最核心的契约是元素不可重复—— 即对于 Set 中的任意两个元素e1和e2必须返回false。无索引:与 List 不同,Set 接口没有定义基于索引的操作方法(如),元素的存储顺序由实现类决定(部分实现类甚至不保证顺序)。去重依据:元素是否重复基于equals()方法判断,但为了提高去重效率,通常会结合hashCode()方法(哈希实现类)或方法(树结构实现类)。HashSetTreeSet,以及线程安全的和。
2025-09-18 17:49:00
631
原创 Vector 底层实现详解
扩容幅度由增长系数决定:增长系数≤0 时默认翻倍,增长系数 > 0 时按固定幅度增长,并非所有情况都是 2 倍。安全兜底逻辑不可忽视:最终容量会强制≥最小所需容量,避免批量添加元素时容量不足。性能开销点:扩容本质是Arrays.copyOf()复制数组,时间复杂度为 O (n),频繁扩容会影响性能。建议初始化时根据业务场景指定合理的initialCapacity和capacityIncrement,减少扩容次数。。
2025-09-17 20:04:14
1097
原创 思考:Nacos中的数据集和application.properties有相同的配置项,哪个生效?
命令行参数(如JVM 系统属性(如Nacos 配置中心配置(默认高于本地配置);本地(如本地;Spring Boot 默认配置。
2025-09-16 21:49:57
996
原创 LinkedList 底层实现与 ArrayList 对比分析
LinkedList 的设计核心是 “双向链表”,它用 “牺牲随机访问效率” 换取 “高效的增删操作”,完美弥补了 ArrayList 在 “频繁增删” 场景中的不足。若以 “查询” 为主,偶尔增删(且多在尾部)→ 选 ArrayList;若以 “增删” 为主(尤其是中间位置),少查询 → 选 LinkedList。
2025-09-16 17:12:28
1131
原创 ArrayList 的底层实现与扩容机制
ArrayList基于索引的快速访问(O (1) 时间复杂度)灵活的自动扩容机制,无需手动管理容量中间位置的增删操作效率低(需要移动元素)扩容会导致数组复制,产生性能开销线程不安全,多线程环境需额外处理了解这些底层原理,能帮助我们在实际开发中更好地选择和使用ArrayList已知元素数量时指定初始容量频繁在中间位置操作时考虑LinkedList批量添加元素时提前调用减少扩容次数ArrayList。
2025-09-16 14:58:29
427
原创 Java 集合框架
需要按顺序存储、可重复、按索引访问→ 选List(优先ArrayList,增删频繁选LinkedList需要去重、无需顺序→ 选Set(优先HashSet,需有序选,需排序选TreeSet需要按顺序处理任务(队列 / 优先级)→ 选Queue(普通队列用LinkedList,优先级任务用需要通过唯一标识(键)快速查找数据→ 选Map(优先HashMap,需有序选,需按键排序选TreeMap。
2025-09-16 14:22:28
477
原创 三色标记算法
三色标记算法是JVM并发垃圾收集的核心技术,通过白、灰、黑三种颜色标记对象状态,实现并发标记。其关键挑战是解决引用关系变化导致的漏标(致命错误)和错标(可接受误差)。工业界采用增量更新(CMS)和原始快照(G1)两种方案:增量更新记录黑色对象新增的引用,原始快照记录灰色对象删除的引用,均在短暂STW阶段修正标记结果。该算法为CMS、G1等现代收集器提供了准确标记存活对象的底层支持。
2025-09-15 23:11:08
653
原创 JVM 垃圾收集器
在 Java 开发中,自动内存管理是其显著优势之一,而这一切的核心就是 JVM 的垃圾收集机制。垃圾收集(Garbage Collection,GC)负责自动识别并回收不再使用的对象,释放内存资源,让开发者无需手动处理内存分配与释放,极大地提高了开发效率并减少了内存泄漏风险。
2025-09-15 19:56:34
963
原创 MySQL 锁机制
简单来说,锁是 MySQL 为保证数据并发访问时的一致性和有效性,而设计的一种资源控制机制。它就像 “资源占坑符”:当一个事务需要操作某部分数据时,先获取对应的锁,防止其他事务同时修改该数据;操作完成后释放锁,让其他事务继续使用。选择锁粒度全库备份 → 全局锁;读多写少、表结构频繁变更 → 表级锁;写多读少、精准修改单行 → 行级锁。选择乐观锁 / 悲观锁商品详情查询、用户信息浏览(读多写少) → 乐观锁;库存扣减、订单支付(写多冲突多) → 悲观锁。规避死锁统一资源访问顺序;
2025-09-15 09:54:05
1098
原创 MySQL 事务
事务(Transaction)是数据库中一组不可分割的操作单元,这组操作要么 “全部执行成功并持久化”,要么 “全部执行失败并回滚”,不存在 “部分生效” 的中间状态。读未提交(Read Uncommitted)读已提交(Read Committed)可重复读(Repeatable Read)串行化(Serializable)。其中,可重复读(Repeatable Read)是 MySQL 的默认隔离级别(区别于 SQL 标准的 “读已提交”)。隔离级别脏读不可重复读幻读丢失修改并发性能。
2025-09-12 15:12:01
890
原创 TCP 三次握手与四次挥手
这是 TCP 三次握手最经典的问题,核心答案是 “确保双方发送能力和接收能力均正常,同时避免‘无效连接请求’浪费资源两次握手不可行:若仅两次握手,服务器发送 SYN+ACK 后就认为连接已建立,但客户端可能因网络延迟未收到该报文,不会发送 ACK。此时服务器会一直等待客户端的数据,浪费端口和内存资源(“半连接队列” 溢出风险);四次握手没必要:三次握手已能完整确认双方的 “发送 + 接收” 能力(客户端确认服务器:能发能收;服务器确认客户端:能发能收),第四次握手属于冗余操作,会增加网络延迟。
2025-09-11 17:56:20
707
原创 Enjoy 模板引擎实现单体不分离开发
在 Spring Boot 生态中,Spring MVC 作为经典的 Web 开发框架,广泛用于构建各类 Web 应用。而在单体不分离架构下,模板引擎是连接后端数据与前端页面的核心桥梁。
2025-09-10 19:05:03
1141
原创 面试常问:注册中心宕机,远程调用还能成功吗?
微服务架构中,注册中心宕机后远程调用能否成功取决于实例缓存:若消费者本地已有目标服务实例缓存(如之前调用过),则调用可继续;若无缓存(首次调用),则因无法获取服务地址而失败。实例缓存机制提升了系统容错性,在注册中心异常时维持部分服务调用能力。
2025-09-10 09:40:01
563
原创 Spring MVC 的常用注解
注解用于标记一个类为 Spring MVC 的控制器。在 Spring MVC 框架里,控制器扮演着关键角色,负责接收 HTTP 请求并返回响应。当一个类被注解标记后,Spring 容器会自动识别并将其纳入管理。
2025-09-09 19:29:50
1046
原创 详解 Spring AOP:核心概念、实现原理与配置实践
AOP(面向切面编程):将与业务无关但被多个业务模块共同调用的共性逻辑(如日志、事务)封装为 “切面”,通过动态织入的方式融入业务流程,以减少重复代码、降低耦合度,提升可维护性与可扩展性1。切面(Aspect): “切点 + 通知” ,它是 AOP 实现的核心载体,包含了 “要增强的方法(切点)” 和 “增强的逻辑(通知)”,例如 “给用户查询方法加日志” 就是一个切面。目标对象(Target):即被代理的对象,也就是包含核心业务逻辑的对象,比如处理用户数据的类。连接点(Join Point)
2025-09-08 15:40:39
818
原创 Spring IOC:控制反转
在传统 Java 开发中,我们创建对象、管理依赖全靠自己new// 传统方式:手动new对象,耦合度极高// 自己new依赖的UserService对象// 直接调用这种方式的问题很明显:如果改了构造方法,或者需要换成它的子类,的代码必须跟着改 —— 这就是 “高耦合”。而 Spring IOC 要做的,就是把 “创建对象、管理依赖” 的控制权从开发者手中 “反转” 给 Spring 框架(也就是 IOC 容器)。以前你主动找对象,现在对象主动来找你。解耦。不再有硬编码的new。
2025-09-05 16:20:52
596
原创 消息中间件:RocketMQ
在微服务架构中,“同步调用” 的痛点(高耦合、级联失败、资源浪费)早已成为系统扩容的绊脚石,而消息中间件的出现,恰好为 “异步通讯” 提供了可靠的解决方案。今天我们就以 Apache RocketMQ 为例,用通俗的语言拆解它的核心架构、关键组件和消息收发流程,帮你快速入门这款企业级消息中间件。
2025-09-04 13:51:12
666
原创 Redis:从基础到 Spring Boot 实战,附企业级解决方案
Redis作为高性能NoSQL数据库,在企业级应用中扮演重要角色。本文系统介绍了Redis的核心特性、数据类型、持久化机制及与SpringBoot的整合方式,重点解析了缓存预热、雪崩、击穿、穿透等企业级问题的解决方案。通过对比RDB和AOF持久化策略,分析内存淘汰机制,并详细讲解互斥锁、逻辑过期等多种缓存治理方案。文章还提供了Java代码示例,帮助开发者从理论到实践全面掌握Redis应用技巧,为构建高并发、高可用的系统提供可靠的技术支持。
2025-09-03 17:54:46
758
原创 SpringBoot的自动配置
定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行逻辑判断,返回一个boolean值。matches 方法的两个参数:判断条件:在初始化Bean时,使用 @Conditional(条件类.class)注解。context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。metadata:元数据对象,用于获取注解属性。
2025-08-25 00:07:57
726
原创 Spring Bean的生命周期
Spring Bean的生命周期是指 Bean 从被 Spring 容器创建、初始化、使用到最终销毁的完整过程。这个过程由 Spring IOC 容器全程管理,包含多个关键阶段,并且预留了丰富的扩展点允许开发者介入。理解 Bean 的生命周期,有助于更好地控制 Bean 的行为(如初始化资源、释放资源等)。执行用户自定义的 Bean 初始化方法。在InitializingBean.afterPropertiesSet()执行完成后触发。
2025-08-17 12:49:40
982
原创 MyBatis的核心组件:Mapper接口和Executor执行引擎
Mapper 和 Executor 都是 MyBatis 的核心组件,二者在框架中承担关键角色,缺一不可,共同支撑 MyBatis 的核心功能 —— 将 Java 方法与 SQL 操作映射并执行。
2025-08-10 23:22:01
966
原创 线程池的核心参数和执行流程
当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会被回收,直到线程池中的线程数不超过corePoolSize。4.如果当前“存活线程数”没有达到最大线程数maximumPoolSize,则创建一个新线程(非核心线程)执行新线程任务;2. 如果线程池中不存在空闲线程,则线程池会判断当前“存活的线程数”是否小于核心线程数corePoolSize。● 如果小于核心线程数corePoolSize,线程池会创建一个新线程(核心线程)去处理新线程任务;
2025-07-30 19:16:01
939
原创 谈谈对CAS的理解
CAS的全称是,中文意思是“比较并交换CAS是由CPU支持的一种对内存中共享数据进行操作的特殊CPU指令,例如cmpxchg。它用于对内存中的共享数据进行原子性的读写操作。进行读写操作时,CPU会比较内存中某个值是否和预期值相同,如果相同,则将这个值更新为新值;如果不相同,则不做更新(或者重试)。Java的核心类都基于CAS机制实现原子性操作。
2025-07-21 19:25:31
787
原创 线程的常用方法
线程被Object.wait(), Thread.join()和Thread.sleep()三种方法阻塞或等待,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常,从而提前终结被阻塞状态。如果线程没有被阻塞或等待,调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()等方法进入阻塞或等待时,才会抛出 InterruptedException异常;当前线程暂停执行,直到调用join()的目标线程执行完毕。
2025-07-17 19:20:52
928
原创 线程基础和线程的状态
现代操作系统(Windows,macOS,Linux)都可以执行多任务。多任务就是同时运行多个任务。例如:播放音乐的同时,浏览器可以进行文件下载,同时可以进行QQ消息的收发。CPU执行代码都是一条一条顺序执行的,但是,即使是单核CPU,也可以同时运行多个任务。因为操作系统执行多任务实际上就是让CPU对多个任务轮流交替执行。操作系统轮流让多个任务交替执行,例如,让浏览器执行0.001秒,让QQ执行0.001秒,再让音乐播放器执行0.001秒。在用户使用的体验看来,CPU就是在同时执行多个任务。
2025-07-16 19:48:35
629
原创 Integer缓存池
Integer缓存池,也称为IntegerCache,是Integer类的静态内部类,用于缓存一定范围内的Integer对象。Integer缓存池默认缓存-128到127之间的整数对象。
2025-02-11 18:31:34
636
原创 StringBuilder类的数据结构和扩容方式解读
StringBuilder类初始化分为无参构造方法初始化和有参构造方法初始化。当使用无参构造方法时,内部char[ ]数组初始化长度为16,当使用有参构造方法时,内部char[ ]数组按照str.length()+16长度进行初始化。扩容的方式是在原数组容量的基础上扩容2倍加上2,代码表现为(value.length<<1) +2。StringBuilder是Java中用于处理可变字符串的类,使用一个字符数组(char[ ] value)来存储实际的字符数据。StringBuilder类的部分源码。
2025-01-31 16:39:23
521
原创 String类的equals()的作用和源代码的解读
在Java中,equals()方法是从Object类继承而来的,而Object类中的equals()方法的默认实现是使用“==”运算符来比较两个对象的引用是否相等,即它们在内存中的地址是否相同。然而,在实际应用中,我们往往更关心的是两个对象的内容是否相等,而不是它们是否是同一个对象。如果发现任何不匹配的字符,则返回false,否则,则说明两个字符串的内容完全相同,返回true。首先,比较当前对象this和要比较的对象anObject是否是同一对象的引用,如果是,则直接返回true。
2025-01-22 23:56:51
549
原创 String为什么是不可变的?
String字符串不可变的原因主要有:1、private(私有的) final(最终的) char[] value:表示内部数组不允许分配地址。由上述举例可以看出,String进行字符串的修改时,不会在原字符串进行修改,而是会产生新的字符串保存修改内容。2、String进行字符串的修改时,不会在原字符串进行修改,而是会产生新的字符串保存修改内容。
2025-01-21 17:54:32
222
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅