自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 面试题24:Spring循环依赖

在设计Bean之间的依赖关系时,尽量避免循环依赖的出现。如果无法避免,优先考虑使用setter注入或者字段注入(通过@Autowired)的方式。如果必须使用构造器注入且出现了循环依赖问题,可以考虑使用@Lazy注解来解决。在使用注解时,要确保其标注的方法中的操作不会引入新的循环依赖或者影响Bean的正常初始化顺序。

2025-08-21 15:13:52 662

原创 面试题23:单例Bean和原型Bean

​​使用@Scope注解:​​ 在类定义上添加或更简洁的。​​XML 配置:​​ 在<bean>元素中设置属性。@Component@Scope("prototype") // 或 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)// ... Bean 的具体实现 ...

2025-08-21 15:10:02 832

原创 每日面试题22:静态代理和动态代理的区别

System.out.println("创建订单:用户" + userId + "购买" + product);维度静态代理动态代理​​代理类生成时机​​编译期(手动/工具生成)运行期(动态生成字节码)​​代码侵入性​​需为每个被代理类编写代理类无需手动编写代理类,通用性强​​维护成本​​高(接口变更需同步修改代理类)低(仅需调整InvocationHandler)​​扩展性​​差(无法动态代理新类)强(一个代理可代理多个类/接口)​​适用场景​​。

2025-08-16 14:50:51 524

原创 每日面试题21:AOP的底层原理

Spring AOP的核心价值在于​​通过动态代理实现横切关注点的模块化​​,其底层依托JDK动态代理(接口场景)和CGLIB动态代理(非接口场景)完成方法增强。理解这两种代理的实现原理、选择策略及注意事项,有助于我们在实际开发中更合理地使用AOP,避免常见的坑(如内部调用失效、final方法增强失败),并充分发挥AOP在解耦、复用、扩展方面的优势。无论是日志记录、事务管理,还是权限校验、性能监控,动态代理技术都让这些横切逻辑的处理变得优雅而高效——这正是Spring AOP的魅力所在。

2025-08-07 13:29:44 865

原创 每日面试题20:spring和spring boot的区别

Spring 定义了企业级 Java 开发的“游戏规则”(IoC/AOP),而 Spring Boot 则是将这套规则“产品化”的工具——它不是替代,而是进化。正如 Spring Boot 官方文档所说:“​​Spring Boot 让 Spring 应用的创建、配置和部署变得前所未有的简单​​”。对于开发者而言,掌握 Spring 核心原理(IoC/AOP)是基础,而熟练使用 Spring Boot 提升开发效率则是现代 Java 工程师的必备技能。

2025-08-03 14:25:00 1272

原创 每日面试题19:深拷贝和浅拷贝的区别

浅拷贝(Shallow Copy)是一种“表面复制”:对于基本数据类型,直接复制值;对于引用数据类型,仅复制对象的地址指针(即新对象与原对象指向同一块堆内存)。深拷贝(Deep Copy)是“彻底复制”:不仅复制对象本身,还会递归复制其所有嵌套的引用类型对象,最终生成一个与原对象​​完全独立​​的新对象(新旧对象不共享任何堆内存)。深拷贝与浅拷贝的本质区别在于​​是否复制引用类型的内存地址​​。浅拷贝是“快捷但共享”的复制,适合简单场景;深拷贝是“彻底但耗时”的复制,适合需要状态隔离的场景。

2025-08-03 14:11:11 567

原创 每日面试题18:基本数据类型和引用数据类型的区别

​​优先基本类型​​:追求性能时(如循环计算),基本类型内存占用小、操作更快。​​使用引用类型​​:需要对象特性时(如集合存储、继承多态),或需要表示"无值"状态(null​​包装类的合理使用​​:集合、反射等场景必须用包装类;注意缓存范围和空指针问题。

2025-08-01 22:56:59 1216

原创 每日面试题17:面向对象OOP的三大特性

封装(Encapsulation)是OOP的基础特性,其核心是​​将对象的属性(数据)和操作属性的方法(行为)绑定在一个类中,并通过访问控制机制隐藏内部实现细节​​。简单来说,就是“把该藏的藏起来,该露的露出来”。继承(Inheritance)是OOP实现代码复用的核心机制,允许一个类(子类/派生类)​​继承另一个类(父类/基类)的属性和方法​​,并可以在此基础上扩展新功能或重写原有方法。通过继承,类之间形成“父子”关系,形成层次化的类结构。多态(Polymorphism)是OOP最强大的特性之一,指​。

2025-07-29 14:52:06 740

原创 每日面试题16:什么是双亲委派模型

​​定位​​:开发者通过继承抽象类实现的扩展加载器;​​场景​​:用于加载非标准路径的类(如网络、数据库、加密文件中的字节码)、实现热部署/热替换等;​​关键方法​​:需重写(推荐)或方法(谨慎修改父类委托逻辑)。在Web容器(如Tomcat)或调试场景中,开发者希望修改代码后无需重启应用即可生效。此时需要​​隔离不同版本的类​Tomcat的会为每个Web应用创建独立的类加载器,优先加载各自和中的类;

2025-07-28 15:59:21 731

原创 每日面试题15:如何解决堆溢出?

堆溢出并非"无解之症",关键在于​​快速定位+精准分析+系统预防​​。通过本文的应急流程和长效策略,可有效降低堆溢出对业务的影响。当发生堆溢出使,先通过报错信息确认错误位置,然后使用jmap命令生成堆转储文件,然后使用Eclipse MAT等工具分析堆内存,之后根据问题适当调整JVM参数,选择适当的JVM垃圾回收机制,并通过一些缉拿空工具实时关注内存的使用情况,可以有效防止堆溢出。

2025-07-26 16:47:28 880

原创 为什么需要可重入锁

Redisson可重入锁的“可重入”核心是​​允许同一线程多次获取同一把锁​​,解决的是复杂业务中嵌套调用(如递归、方法调用链)导致的锁冲突问题。其本质是“同一线程的锁重用”,而非“不同业务的锁共享”。锁值(重入次数)记录了当前线程持有锁的次数,只有当次数减至0时,锁才真正释放。这一设计避免了开发者手动维护嵌套锁的复杂性,是分布式系统中处理复杂业务逻辑的重要工具。

2025-07-25 10:54:14 503

原创 每日面试题14:CMS与G1垃圾回收器的区别

CMS与G1的差异,本质上是JVM对“延迟”与“吞吐量”、“固定分代”与“动态分区”、“并发效率”与“内存整理”的平衡选择。随着ZGC(Z Garbage Collector)等更先进的回收器出现(目标停顿<10ms),GC的设计仍在向“更智能、更可控”的方向演进。但对于大多数企业级应用而言,理解CMS与G1的核心差异,仍能为我们的技术决策提供坚实的基础。下次遇到GC性能问题时,不妨先看看堆内存的大小、应用的延迟要求,再想想:是该让CMS的并发回收“轻踩油门”,还是让G1的分区策略“精准控速”?

2025-07-25 10:44:42 804

原创 Docker

Docker 是容器化技术的代表,核心价值是​​标准化、轻量级、可移植​​,能高效搭建多实例服务(如多个 Redis)。运维的核心是保障应用稳定运行,而 Docker 深度融入运维的监控、部署、故障处理等环节,是现代运维的必备工具。深入学习需结合理论与实践,从搭建简单容器开始,逐步掌握编排、监控和集群管理等高级技能。

2025-07-24 16:40:41 390

原创 每日面试题13:垃圾回收器什么时候STW?

CMS通过并发标记和清除大幅减少了STW时间,但初始标记和重新标记仍需短暂停顿。其STW总耗时通常在10ms~100ms级别(取决于堆大小和对象复杂度)。G1的STW主要集中在初始标记、最终标记和筛选回收阶段,但通过并发标记和SATB算法大幅缩短了单次STW的时间。由于G1支持"增量回收"(每次只回收部分Region),其平均STW时间可控制在用户设定的阈值内(如不超过200ms)。

2025-07-23 10:48:48 1187

原创 Java自动拆箱机制

在黑马点评项目中,提到了一个细节,就是Java的自动拆箱机制,本文来简单了解一下。Java 的​​是一种编译器层面的语法糖,用于简化​​(如IntegerBooleanLong等)与​​(如intbooleanlong等)之间的转换。它的核心作用是让开发者无需手动调用intValue()等方法,即可直接在包装类对象和基本类型之间赋值或运算。

2025-07-22 22:01:35 698

原创 实现分布式锁

​:MySQL是传统关系型数据库,Redis是高性能内存数据库,ZooKeeper是分布式协调工具(虽能存数据,但核心是解决分布式系统的一致性问题)。

2025-07-22 22:00:17 477

原创 Lua语言

在黑马点评项目实战中,在提到确保分布式锁的获取锁和释放锁的时候提到了Redis的Lua脚本,本文来简单介绍一下Lua语言和简单语法。

2025-07-22 21:12:39 835

原创 每日面试题12:JVM垃圾回收机制

JVM会从一组称为​​GC Roots​​的根对象出发,通过引用链(Reference Chain)遍历所有能被访问到的对象。这些被遍历到的对象被标记为“存活对象”,反之则被视为“垃圾对象”,等待回收。JVM垃圾回收机制是Java高效运行的基石,理解不同回收器的原理与适用场景,能帮助开发者根据业务需求选择最优配置,平衡性能与资源消耗。随着JVM技术的演进(如ZGC的普及),未来的GC将更智能、更高效,持续赋能高并发、低延迟的现代应用。

2025-07-22 11:19:11 947

原创 synchronized 修饰符的使用

是 Java 的同步关键字,通过对象锁保证多线程下代码块的原子性,用于解决线程安全问题。intern()是字符串的池化方法,确保相同内容的字符串共享常量池中的同一引用,避免锁对象不一致导致的同步失效。字符串常量池是内存优化机制,通过去重减少重复对象的内存占用。代码中使用是为了确保同一用户的不同线程锁定同一对象,实现“一人一单”的线程安全控制;不加intern()会导致锁失效,引发并发问题。

2025-07-21 18:00:16 848

原创 事务注解可能失效的几种可能原因

在黑马点评项目的学习过程中,我遇到了事务失效的问题,其中提到了事务失效的可能原因,本文就来简单了解一下事务实现的可能原因是什么。

2025-07-21 17:57:37 871

原创 每日面试题11:JVM

JVM不仅是Java跨平台的“桥梁”,更是程序运行的“资源管家”。它的核心架构(运行时数据区、类加载器、执行引擎、GC)协同工作,确保了Java程序的高效、安全与稳定。下次遇到或OOM时,不妨回忆一下JVM的内存结构——问题可能就出在某个区域的“超载”;而理解类加载器和GC机制,则能帮你写出更健壮、更高效的Java代码。

2025-07-21 15:50:13 1168

原创 乐观锁和悲观锁

​​悲观锁​​:强一致性,适合高冲突场景(如秒杀库存),但可能牺牲性能。​​乐观锁​​:高并发友好,适合低冲突场景(如普通库存),但需处理重试逻辑。​​其他锁​​:根据场景选择(读多写少用读写锁,分布式用Redis锁,无锁用CAS),核心目标是平衡一致性、性能和复杂度。

2025-07-20 17:42:32 1058

原创 每日面试题10:令牌桶

令牌桶算法以其优雅的设计,在"严格限制"与"灵活应对"之间找到了完美平衡。它既像一位严谨的交通警察,确保请求有序通过;又像一位贴心的服务生,在高峰期能灵活调配资源。理解并合理应用令牌桶算法,将为你的系统构筑起一道可靠的流量防线。​​实践建议​在API网关层实施全局限流关键业务接口设置独立令牌桶结合熔断降级机制形成完整防护链。

2025-07-20 17:13:09 987

原创 每日面试题09:进程、线程、协程的区别

进程、线程、协程的本质是​​操作系统对资源分配与任务执行的抽象分层​进程通过内核级隔离保障系统稳定性,是「安全屋」;线程通过共享资源提升执行效率,是「协作伙伴」;协程通过用户态调度优化并发性能,是「效率引擎」。在实际开发中,选择何种模型需结合具体场景:需要安全选进程,需要效率选线程,需要并发选协程——或者,三者结合(如「多进程+多线程+协程」的混合架构),以发挥各自的优势。

2025-07-19 11:07:51 1108

原创 每日面试题08:wait()和sleep()的区别

wait()是Object类的实例方法(所有Java对象都拥有此方法),其核心作用是让当前线程进入等待状态。但​​必须在持有对象监视器锁的前提下调用​​(即必须在同步块或方法中),否则会抛出异常。// 正确调用:在synchronized块中持有锁// 合法调用// 错误调用:未持有锁时调用// 抛出IllegalMonitorStateExceptionsleep()是Thread类的静态方法(),直接通过调用。它不依赖任何锁,即使线程未持有对象监视器锁也可以调用。// 直接调用,无需同步块。

2025-07-18 10:47:49 928

原创 Redis集群的哨兵模式

​​主节点(Master)​​:负责处理读写请求,数据变更后同步到从节点(Slave/Replica)。​​从节点(Slave)​​:只读,通过全量复制(首次连接时)和增量复制(持续同步)保持与主节点数据一致。但主从复制存在致命缺陷:​​主节点故障时,需人工介入将某个从节点提升为新主节点,并调整其他从节点指向新主节点​​。这在高并发场景(如电商大促)中会导致服务中断,无法满足可用性要求。哨兵模式是Redis官方推出的​​分布式高可用解决方案​。

2025-07-17 11:22:06 1098

原创 每日面试题07:线程池的工作流程

线程池的工作流程可以概括为:​​任务提交 → 检查核心线程(是否空闲) → 核心线程忙则入队 → 队列满了创建非核心线程 → 线程数满了触发拒绝策略​​。核心参数(workQueuehandler)的组合决定了线程池的行为,而阻塞队列的选择是其中的关键——它直接影响了任务是“排队等线程”还是“挤不下了直接拒绝”。理解线程池的底层逻辑,能帮助我们在实际开发中更合理地配置线程池参数,避免资源浪费或系统崩溃,让并发程序更高效、稳定地运行。

2025-07-17 10:38:47 1214

原创 二进制运算

​​逻辑运算​​(与、或、异或、非)是计算机执行条件判断、位操作的基础,支撑着程序流程控制和数据加密;​​算术运算​​(加减乘除)是数值计算的核心,支撑着科学计算、工程模拟等复杂任务;其中,异或因其“相同为0,不同为1”的独特规则,在加密、校验、位操作中表现突出,是计算机组成原理中最具实用性的逻辑运算之一。

2025-07-15 16:02:01 656

原创 JUC工具类

CountDownLatch 是 JUC 中用于线程协调的同步工具类,而 JUC 是 Java 并发编程的核心工具包,覆盖了锁、原子操作、并发集合、线程池、异步编程等几乎所有多线程场景。掌握这些工具类能显著提升多线程程序的性能和可靠性。

2025-07-15 15:32:36 652

原创 Mysql默认存储引擎InnoDB和底层数据结构

InnoDB 选择 B+树而非红黑树,本质是为了满足​​磁盘存储的高效性​​和​​事务场景的复杂性​​。B+树通过多路平衡、顺序存储、链表连接等设计,完美解决了数据库索引的核心痛点(范围查询、高并发写入、磁盘 IO 优化)。在黑马点评项目中,我们选择 RedisINCR作为全局唯一ID生成方案,正是基于对 InnoDB 特性的深度理解:RedisINCR生成的严格递增 ID,与 InnoDB 聚簇索引的顺序写入特性完美匹配,大幅提升了订单表的写入性能。​​一句话总结​。

2025-07-15 13:32:59 1007

原创 分布式全局唯一ID生成:雪花算法 vs Redis Increment,怎么选?

​​优点​​:本地生成、性能极高;趋势递增对数据库友好;ID可解析,便于排查问题。​​缺点​​:依赖本地时钟(时钟回拨需处理);机器ID需提前规划(扩展性受限)。雪花算法是“本地生成的高性能分布式ID引擎”,适合高并发、无中心、需要ID携带信息的场景;Redis Increment是“依赖外部服务的递增ID生成器”,适合已有Redis基础设施、需要严格递增的场景。选择时,核心考虑点:​​是否需要严格递增?是否依赖外部服务?对性能和延迟的要求?​​ 没有绝对最优,只有最适合业务的方案。

2025-07-15 11:28:31 1178

原创 每日面试题06:自定义线程池与线程池工厂

通过构造函数自定义线程池时,需要显式指定以下核心参数。这些参数共同决定了线程池的行为模式和资源分配策略。​​自定义线程池​​:优先使用构造函数,根据业务场景调整参数(如根据常驻任务量设置,workQueue根据任务特性选择有界/无界队列)。​​避免OOM​​:尽量使用有界队列(如),并合理设置;拒绝策略推荐(减缓任务提交)或(丢弃旧任务)。​​官方建议​​:《Java并发编程实战》明确指出,直接使用Executors工厂方法可能隐藏线程池的实际配置,推荐显式通过构造函数创建,以提高透明度和可控性。

2025-07-15 10:47:10 692

原创 @Resource和@Autowired

拦截器是 Spring MVC 处理请求的核心组件,负责在请求到达 Controller 前/后执行逻辑(如 Token 校验、日志记录)。在拦截器中使用依赖注入时,​​构造器注入比字段注入更优​在自定义拦截器中,构造器注入相比字段注入(@Autowired​​强制依赖有效性​​:确保拦截器实例创建时所有必需依赖已就绪,避免运行时 NPE。​​线程安全​final字段保证依赖不可变,符合单例 Bean 的线程安全要求。​​代码清晰​​:显式声明依赖,降低维护成本。​​测试友好​。

2025-07-14 16:42:42 2076

原创 每日面试题05:ArrayList和LinkedList的底层原理

ArrayList和LinkedList的选择没有绝对答案,关键在于​​场景匹配​若需​​高频随机访问​​(如遍历、按索引操作),选ArrayList;若需​​高频头尾插入/删除​​(且数据量不大),选LinkedList(或更优的ArrayDeque内存敏感场景,优先ArrayList(紧凑存储更省内存);多线程环境,根据需求选择线程安全的扩展实现(如或理解底层原理后,结合具体业务场景的性能瓶颈(如访问频率、插入位置、数据量),才能做出最优选择。

2025-07-13 22:23:48 846

原创 每日面试题04:volatile字段的原理

volatile是 Java 的关键字,用于修饰​​共享变量​​。​​可见性​​:确保线程对变量的修改立即同步到主内存,其他线程能立即看到最新值;​​有序性​​:禁止编译器和 CPU 对变量的读写指令进行重排序,保证代码执行顺序与编写顺序一致。简单来说,volatile是多线程环境下的“变量同步器”,让共享变量的修改在多线程间“可见”,且操作“有序”。volatile​​适用场景​​​​原因​​状态标志(如线程启停)仅需单次读写,无需复合操作,volatile轻量且高效。单例模式的DCL。

2025-07-12 21:31:00 708

原创 单体架构与分布式架构的事务机制

​​维度​​​​单体架构()​​​​分布式系统(以 Seata 为例)​​​​注解类型​​(Spring 原生)(Seata 扩展)​​管理范围​​单个服务内的本地事务(同一数据库)跨多个服务的分布式事务(多数据库)​​底层依赖​​数据库原生事务(如 MySQL InnoDB)分布式事务协调器(TC)+ 本地事务(可能用​​实现复杂度​​简单(框架自动管理)复杂(需引入 TC、配置事务分组、处理网络异常)​​典型场景​​本地业务逻辑(如用户注册+日志记录)

2025-07-12 17:04:17 657

原创 每日面试题03:CAS的底层原理及其ABA问题

​​CAS的核心​​:通过CPU原子指令实现无锁的“比较+交换”操作,是高效并发的基础。​​ABA问题的本质​​:CAS仅比较值是否相等,无法感知中间修改,可能导致逻辑错误。​​解决方案​​:引入版本号(如)跟踪修改历史,或根据业务场景忽略ABA问题,或改用锁机制。​​关键结论​​:CAS是无锁并发的利器,但需警惕ABA问题的潜在风险。通过版本号或锁机制可有效规避,确保程序逻辑正确性。

2025-07-12 09:43:55 1007

原创 线程安全问题

线程安全问题的本质是:​​多个线程并发访问共享资源(如内存数据结构、缓存、数据库等)时,由于操作顺序未同步或同步机制缺失,导致数据不一致、脏读、幻读等不符合预期的结果​​。其核心矛盾在于“共享资源的并发修改未被正确控制”。举个通俗的例子:若两个线程同时对一个共享变量count执行count++操作(本质是),若没有同步机制,可能出现线程A读取count=5后未写入,线程B也读取count=5并写入6,最终count仅变为6而非预期的7。这就是典型的线程安全问题。多线程环境下的线程安全问题,本质是​。

2025-07-11 09:42:33 791

原创 每日面试题02:ConcurrentHashMap的底层原理

是 Java 并发包()中提供的​​线程安全哈希表实现​​,专为高并发场景下的键值对存储设计。它在保证线程安全的同时,通过优化锁机制和数据结构,显著提升了多线程环境下的性能。​​底层结构​​:与HashMap同源,均基于​​哈希表(数组+链表/红黑树)​​实现,核心逻辑(如哈希冲突解决、扩容机制)高度一致。HashMap是非线程安全的哈希表,适合单线程或低并发场景;是线程安全的哈希表,通过 CAS、和细粒度锁机制,在多线程高并发场景下保证数据一致性,同时保持高性能。

2025-07-10 22:27:59 942

原创 线程与异步相关问题

​​优先异步​​:当任务以I/O为主(等待时间长、CPU空闲),或需要高并发低资源消耗时(如实时通信、Web服务器),异步(尤其是单线程事件循环)更优。​​优先多线程​​:当任务以计算为主(CPU密集),或需要利用多核并行加速时(如大数据处理、科学计算),多线程更优。​​混合使用​​:复杂系统中,可结合两者(如异步处理I/O,多线程处理计算),平衡成本与效率。

2025-07-10 16:41:22 794

空空如也

空空如也

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

TA关注的人

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