- 博客(64)
- 收藏
- 关注
原创 >>(带符号右移)和 >>>(无符号右移)的区别
操作符高位填充内容对负数的影响典型用途>>补符号位(0 或 1)保持负数性质(结果仍为负数)有符号数的除法(/2ⁿ)>>>始终补 0结果变为正数(符号位被覆盖)无符号数的位运算处理。
2025-09-04 16:29:40
512
原创 redisTemplate.opsForValue().bitField() 方法返回 List<Long> 而非单个 Long的原因
BITFIELD命令支持多子命令,因此返回结果是集合类型。Spring Data Redis 为了兼容多命令场景,统一返回List<Long>。单个子命令时,取列表第一个元素即可得到目标Long值。这种设计保证了 API 的一致性,无论执行多少个子命令,返回类型都保持统一。
2025-09-04 16:12:21
424
原创 ThreadLocal为什么会发生内存泄露
虽然一个 实例只能存储一个值(每个线程一份),但内存泄漏的风险不是来自“存多个数据”,而是来自“长期持有不再需要的数据引用”,尤其是在使用线程池的场景下。我们来一步步拆解这个问题:你说得对,每个 实例在每个线程中只能关联一个 类型的值。例如:所以,单个 不会“堆积”多个值。问题的关键在于 线程的生命周期 和 的内部结构。会发生什么?这就是 内存泄漏:本应被释放的对象,因为被意外持有引用而无法回收。你可能会问:不是 key 是弱引用吗?那不是会自动清理吗?是的, 实例作为 key 是弱引
2025-08-27 23:27:28
684
原创 ThreadLocal中为什么key要设置为弱引用,value设置为强引用
项目引用类型原因key (实例)弱引用避免实例无法被回收,导致内存泄漏value (本地变量)强引用保证只要线程需要,就能访问到数据注意:弱引用 key 只是缓解了内存泄漏问题,真正防止内存泄漏的关键是开发者主动调用remove()方法。所以,的设计是“尽力而为”的内存管理策略:通过弱引用减少泄漏风险,但仍需开发者配合清理。
2025-08-27 23:25:30
491
原创 Redisson看门狗策略
Redisson 看门狗通过 “自动续期” 机制,完美解决了分布式锁 “过期时间设置难题”,确保锁在业务完成前不会提前释放,同时避免了死锁风险。无需手动估算过期时间,自动适配业务执行时长,是分布式锁的最佳实践之一。
2025-08-26 22:51:50
428
原创 Spring中第三级缓存的作用
第一级缓存(singletonObjects):存放完全初始化完成的单例 Bean(可以直接使用的最终实例)。第二级缓存(earlySingletonObjects):存放提前暴露的早期实例(未完全初始化,但已实例化的原始对象或代理对象)。第三级缓存(singletonFactories):存放Bean 的工厂对象(ObjectFactory),用于在需要时生成 Bean 的早期引用(可能是原始对象,也可能是 AOP 代理对象)。第三级缓存(singletonFactories)的核心作用。
2025-08-25 22:35:14
1180
原创 Spring框架中单例Bean是否是线程安全的
Spring 单例 Bean 的线程安全性取决于 Bean 是否包含共享可变状态:无状态 Bean 线程安全,有状态 Bean 线程不安全。Spring 不直接保证线程安全,需要开发者根据业务场景选择合适的同步策略(如锁、、原子类等)。最佳实践:尽量设计无状态的单例 Bean(如 Controller、Service、Repository 通常是无状态的),从根源上避免线程安全问题。
2025-08-25 22:03:29
953
原创 串行化和可重复读的区别
串行化是SQL 标准中最高的事务隔离级别强制所有事务按 “串行顺序” 执行(而非并发执行),即一个事务完全结束后,另一个事务才能开始。这种 “排队执行” 的方式从根本上避免了所有并发冲突,是唯一能解决脏读、不可重复读、幻读三大问题的隔离级别。串行化是最高隔离级别,通过强制事务串行执行 + 严格锁定,解决所有并发问题(包括幻读),但牺牲了并发性能;可重复读(标准)的核心是通过 MVCC 保证 “单行版本一致”,解决不可重复读,但因无法阻止 “范围间隙的新行插入”,故无法解决幻读;
2025-08-25 21:19:22
622
原创 CMS中写屏障和增量更新
写屏障:是拦截引用修改的 “钩子”,让回收器感知到对象引用的变化。增量更新:是利用写屏障实现的策略,通过将 “新增引用白色对象的黑色对象” 重新标记为灰色,确保白色对象能被重新遍历和标记。两者配合解决了并发标记阶段的漏标问题,是 CMS 等并发垃圾回收器能正确工作的核心保障。
2025-08-23 21:50:21
459
原创 三色标记中例子说明
D 从始至终没有被任何 “可达路径” 覆盖,因此始终保持白色(未被标记)。D 的初始状态D 是一个孤立对象(没有任何 GC Roots 或存活对象引用它,即D → E这个引用链本身不被 GC Roots 可达)。标记过程中从未被遍历没有任何灰色对象会遍历到 D(D 没有被任何存活对象引用);写屏障也不会处理 D(因为没有存活对象引用 D,不会触发 “新增引用到 D” 的操作)。因此,D 始终保持初始的白色,标记结束后被判定为垃圾。
2025-08-23 21:33:01
411
原创 CMS三色标记
三色标记是 CMS 并发标记的核心算法,通过白、灰、黑三色追踪对象存活状态,实现高效的并发标记。漏标问题通过 “写屏障 + 增量更新” 解决:当黑色对象引用白色对象时,强制将黑色对象变回灰色,确保子对象被重新标记。三色标记的优势:允许应用线程与回收线程并发执行,大幅减少 STW 时间,适合低延迟场景(如 Web 服务)。这种机制平衡了垃圾回收的准确性和应用的可用性,是并发垃圾回收器的关键技术。
2025-08-23 21:19:07
607
原创 并发垃圾回收器
并发垃圾回收的执行流程围绕 “标记存活对象→清除垃圾” 展开,通过将耗时的标记和清除阶段与应用线程并发执行,仅在必要时短暂暂停应用,实现低停顿目标。其核心是平衡回收效率与应用可用性,典型代表如 CMS(侧重低延迟)和 G1(兼顾延迟与吞吐量)。
2025-08-23 21:12:17
853
原创 并发清除阶段详细
问题是否存在原因 / 解决机制产生新垃圾(浮动垃圾)是应用线程与回收线程并发执行,新垃圾只能等到下一次 GC 处理误清除存活对象否通过写屏障跟踪引用修改,强制保护存活对象,确保未标记的存活对象不会被误删本质上,并发清除阶段的设计是 “牺牲部分内存效率(容忍浮动垃圾),换取应用低停顿,同时通过写屏障确保内存安全这也是所有并发垃圾回收器(包括 CMS、G1)的核心权衡逻辑 —— 既要让应用少停顿,又要绝对避免内存安全问题。
2025-08-23 20:21:45
510
原创 指令重排的原因
指令重排是编译器和 CPU 的性能优化手段,单线程下无害,但多线程下可能破坏数据一致性。理解指令重排的风险,是编写线程安全代码的关键(例如用volatile禁止重排,或用同步机制保证顺序)。
2025-08-23 17:40:43
322
原创 自旋锁的过程
自旋获取锁的核心是 “循环重试而非立即阻塞”,通过消耗少量 CPU 时间换取线程状态切换的开销。它是 JVM 轻量级锁的实现基础,在并发程度低、锁持有时间短的场景下能显著提升性能,但需避免在激烈竞争或长耗时同步块中使用。
2025-08-23 13:48:41
336
原创 偏向锁→轻量级锁→重量级锁的介绍
偏向锁:单线程无竞争,通过 “记住线程 ID” 避免加锁开销。轻量级锁:少量线程交替竞争,通过 CAS 自旋减少阻塞。重量级锁:多线程激烈竞争,通过操作系统互斥量保证同步,牺牲性能换稳定性。JVM 通过这种 “按需升级” 的机制,在不同并发场景下平衡了同步安全性和性能,是从 “重量级锁” 优化为高效同步机制的核心原因。
2025-08-23 11:34:52
967
原创 Static关键字的详解
static定义共享数据(静态变量);实现工具方法(静态方法);执行类初始化逻辑(静态代码块);定义独立于外部类实例的内部类(静态内部类)。合理使用static可以简化代码、提高效率,但需注意其对代码灵活性和线程安全的影响。
2025-08-22 23:08:04
458
原创 线程池的执行流程
线程池的执行流程本质是 “优先使用核心线程→再用队列缓冲→最后创建临时线程→超出则拒绝” 的资源分配策略,通过这种分层处理,既保证了任务的高效执行,又避免了线程无限制创建导致的系统资源耗尽问题。理解这一流程是合理配置线程池参数的基础。
2025-08-22 22:57:08
521
原创 网络请求密集型和CPU密集型场景下,线程池参数的设置
场景核心线程数(corePoolSize)最大线程数(maximumPoolSize)队列(workQueue)核心思路CPU 密集型CPU 核心数 或 CPU 核心数 + 1等于核心线程数大容量有界队列减少 CPU 上下文切换,提高计算效率网络请求密集型CPU 核心数2 ~ CPU 核心数4核心线程数的 1.5~2 倍小容量有界队列利用 IO 等待时间,增加并发处理能力实际调优建议。
2025-08-22 22:54:44
625
原创 依赖注入的理解
依赖注入(Dependency Injection,简称 DI)是面向对象编程中,核心是 “”,从而降低代码耦合度,提高灵活性和可测试性。
2025-08-22 22:01:28
839
原创 ofType和javaType的区别
属性作用对象适用场景示例javaType属性本身的类型所有类型(简单类型、对象、集合)声明address是对象;声明orders是List集合。ofType集合中元素的类型仅集合类型(ListSet等)声明List中元素是Order对象。
2025-08-22 21:15:53
423
原创 索引对查询(SELECT)和写入(UPDATE/INSERT)效率的影响
索引对查询友好:通过预先构建的有序结构,减少查询时的扫描范围,提高SELECT效率。索引对写入不友好:写入时需同步维护索引结构(插入、删除、平衡),增加额外的 IO 和计算开销,降低UPDATEINSERT效率。不为不常用的查询建索引,不为频繁写入的字段建过多索引,避免 “为了查询快一点,让写入慢很多”
2025-08-21 23:02:11
396
原创 ACID 和 CAP的区分
ACID 是单机数据库事务原子性(Atomicity):事务是不可分割的最小单位,要么全部执行成功,要么全部失败回滚(如转账操作要么双方余额同时更新,要么都不更新)。一致性(Consistency):事务执行前后,数据必须从一个合法状态转换到另一个合法状态,符合业务规则(如转账后双方总余额不变)。隔离性(Isolation):多个事务并发执行时,彼此的操作互不干扰,避免脏读、不可重复读等问题(通过隔离级别控制,如读已提交、可重复读)。持久性(Durability)
2025-08-21 22:30:29
624
原创 Class.forName() 和 ClassLoader 的区别
特性核心功能加载类 + 执行静态初始化(默认)仅加载类,不执行静态初始化底层依赖内部调用 ClassLoader,但多了初始化步骤类加载的核心工具,仅负责加载字节码典型场景加载数据库驱动、需要立即初始化的类动态加载类信息、延迟初始化场景是否执行静态代码块是两者最直观的区别。
2025-08-21 11:36:53
386
原创 可作为GC Root的对象类型有什么?
正在使用的局部变量(栈中)、静态变量(方法区)、常量(方法区);活跃线程、JNI 引用、被同步锁持有的对象等。垃圾回收器通过这些根节点,逐层遍历引用链,最终确定哪些对象可以被安全回收。
2025-08-21 10:14:43
523
原创 日期格式化中yyyy 和 YYYY 的区别
符号含义适用场景注意事项yyyy自然年(1-12 月)绝大多数日常日期格式化推荐优先使用YYYY周所在的年份(ISO 周历)需按周统计年份的场景(如财务周报表)避免在普通日期场景中使用,易导致年份错误记住:日常开发中,用yyyy表示年份即可,YYYY仅在明确需要按周历规则处理年份时使用。
2025-08-20 19:29:20
456
原创 Redis是单线程却可以支持高并发的原因
简单来说,它允许单线程同时监听多个网络连接的 I/O 事件(如 “客户端发送数据”“数据发送完成” 等),并能快速定位到 “已就绪” 的连接进行处理,而无需为每个连接创建单独的线程。Redis 的单线程模型并非 “限制”,而是通过规避多线程开销依托内存高速访问借助 I/O 多路复用处理网络请求,以及简化命令设计,最终实现了高并发处理能力。并发性能并非一定要依赖多线程,针对场景优化设计(如减少阻塞、提高单线程效率)同样能达到高性能目标。
2025-08-20 18:27:24
1049
原创 Strings与new String()的区别
写法对象创建位置常量池使用情况内存效率仅常量池(最多 1 个)优先复用常量池已有对象高(复用机制)堆内存(至少 1 个)可能触发常量池创建(若不存在)低(新对象)
2025-08-20 18:25:16
544
原创 Spring IOC的加载流程
这一阶段不创建 Bean 实例,只完成 “Bean 的元数据收集和注册”,相当于 “根据图纸准备好所有零件的清单”。找配置:定位资源(XML / 注解);读配置:解析成 BeanDefinition(元数据);记配置:注册 BeanDefinition 到注册表;改配置:通过 BeanFactoryPostProcessor 修改定义;造对象:实例化 Bean(反射创建);填依赖:依赖注入(设置属性和依赖 Bean);做初始化:执行 Aware 接口、初始化方法、后置处理器增强;用 Bean。
2025-08-19 19:53:17
1141
原创 Spring如何解决Bean的循环依赖
Spring 解决单例 Bean 循环依赖的核心是:在 Bean 实例化后、初始化前,通过三级缓存提前暴露半成品对象,让依赖方可以先获取到这个半成品,从而打破循环等待。三级缓存的设计还兼顾了 AOP 代理的动态生成,确保依赖注入的是正确的对象(原始对象或代理对象)。
2025-08-19 19:49:27
1415
原创 虚引用的作用----大白话版
比如你用了一块 “堆外内存”(不在 JVM 管的范围内),普通的垃圾回收管不了它。这时候就可以给对应的 Java 对象挂个虚引用,等这个对象被回收时,虚引用一 “喊”,你就知道 “哦,该手动释放那块堆外内存了”,避免内存浪费。它不能像普通引用那样用对象(比如调方法、拿数据),啥用没有,唯一的活儿就是:当它盯的那个对象被垃圾回收器收走时,它会跳出来 “喊一声”(被放进一个专门的队列里)。简单说:它啥也干不了,就负责在对象被回收时 “报个信儿”。虚引用就像个 “垃圾回收报警器”。
2025-08-18 17:21:21
127
原创 UNION 和 UNION ALL的区别
特性UNIONUNION ALL去重自动去重不处理重复,保留所有行性能较低(需排序和比对)较高(直接拼接)适用场景需要唯一结果集时允许重复或已知无重复时选择时,优先考虑UNION ALL(性能更优),仅在明确需要去重时使用UNION。
2025-08-18 15:22:08
584
原创 ConcurrentHashMap为什么放弃Segment?
Segment 的固定并发度、粗粒度锁和高内存开销已无法满足高并发场景的需求。Java 8 改用 CAS + 细粒度 synchronized 的方案,在并发性能、灵活性和内存效率上实现了全面超越,更适应现代硬件和高并发业务的挑战。
2025-08-18 15:16:15
558
原创 CompletableFuture 方法使用
提供了丰富的方法用于异步任务的创建、结果处理、任务组合和异常处理,这些方法可分为创建异步任务、结果处理(链式操作)、任务组合和异常处理四大类。以下是核心方法的详细介绍:用于启动异步任务,返回 实例。示例:二、结果处理(链式操作)当异步任务完成后,对结果进行处理(转换、消费等),支持链式调用(每个方法返回新的 )。示例: 与 区别:上述 方法默认使用任务的 “完成线程” 执行回调(可能是异步任务的线程,也可能是调用线程)。若需指定线程池,可用以下方法:示例:四、多任务组合用于协
2025-08-18 10:11:16
641
原创 CountDownLatch 的原理
通过计数器的增减实现线程间的同步,核心是 “等待方” 阻塞至 “计数器归零”,适用于一次性的多线程协作场景。实现,AQS 是 Java 并发工具的基础框架,用于管理线程的等待队列和状态同步。)中的一个同步工具类,用于协调多个线程之间的执行顺序,其核心原理是通过一个。),该值通常代表需要等待的任务数量或事件数量。计数器一旦减到 0,就无法再被重置(与。实例时,需要指定一个初始计数器值(当某个任务或事件完成时,线程调用。表示需要等待 3 个事件完成。而阻塞的线程,让它们继续执行。控制线程的等待与唤醒。
2025-08-18 10:07:55
405
原创 CompletableFuture的原理
通过CAS 操作管理任务状态(未完成 / 完成 / 异常),保证线程安全。依赖线程池执行异步任务,任务完成后自动更新状态。通过依赖链注册回调,任务完成时自动触发后续操作,实现非阻塞处理。支持多任务组合和异常传播,简化复杂异步场景的编程。这种设计让异步编程从 “主动等待结果” 转变为 “被动接收通知”,大幅提升了代码的可读性和效率,尤其适合处理多步骤依赖的异步任务(如分布式调用、IO 操作等)。
2025-08-18 10:05:46
768
原创 Redisson实现延迟队列
Component// 目标队列名称(延迟消息到期后转移到该队列)@Resource// 初始化延迟队列和消费者// 1. 获取目标队列(普通队列)// 2. 创建延迟队列(关联目标队列)// 3. 监听目标队列,处理到期的消息System.out.println("处理延迟消息:" + message + ",当前时间:" + System.currentTimeMillis());});// 发送延迟消息// 添加消息到延迟队列,指定延迟时间。
2025-08-17 11:33:05
805
原创 XXL-JOB 和 Spring Task 的区别
XXL-JOB 专为分布式环境设计,提供了 Spring Task 缺失的分布式协调、可视化管理、任务分片、监控告警等生产级特性。对于单机应用或极简单的定时任务,Spring Task 足够轻量;但在分布式系统中,XXL-JOB 能显著降低任务调度的复杂度,保证任务执行的一致性和可靠性,是更优选择。
2025-08-16 21:07:52
761
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人