面试小总结

Q1:Java 内存模型(JMM)是什么?作用是什么?
A:JMM 是抽象模型,定义了线程和主内存之间的交互规则:所有变量存在主内存,线程操作时将变量加载到工作内存,操作后写回。作用是解决多线程内存可见性、原子性、有序性问题 ,是 synchronized、volatile 等并发关键字的底层依据。

Q2:垃圾回收(GC)的流程?常见的垃圾收集器有哪些?
A:流程分三步:①通过可达性分析(GC Roots)判断对象是否存活;②回收存活对象内存(清除 / 标记 - 复制 / 标记 - 整理);③内存分配(指针碰撞 / 空闲列表)。
常见收集器:SerialGC(单线程,简单高效)、ParallelGC(多线程,注重吞吐量)、G1(区域化分代,兼顾吞吐量与延迟)、ZGC/Shenandoah(低延迟,大堆场景)。

Q3:类加载机制的流程?什么是双亲委派模型?
A:类加载流程:加载(读字节码)→验证(校验字节码合法性)→准备(静态变量赋默认值)→解析(符号引用转直接引用)→初始化(执行 clinit 方法)。
双亲委派:加载类时,先委托父加载器(Bootstrap→Extension→Application),父加载器无法加载时才自己加载。作用是防止类重复加载、保证核心类安全 (如 java.lang.String 不会被自定义类篡改)。

Q1:HashMap 的实现原理?JDK 1.7 和 1.8 有什么区别?
A:底层是数组 + 链表(JDK1.7)/ 数组 + 链表 + 红黑树(JDK1.8) ,通过 key 的 hashCode 计算索引,解决哈希冲突。
区别:①1.7 用头插法(多线程可能死循环),1.8 用尾插法;②1.8 当链表长度≥8 时转红黑树(≤6 时退化为链表);③1.8 的 hash 计算更简单(减少扰动)。

Q2:ArrayList 和 LinkedList 的区别?分别适合什么场景?
A:①底层:ArrayList 是动态数组(连续内存),LinkedList 是双向链表(离散内存);②性能:ArrayList 随机访问快(O (1))、增删慢(需移动元素,O (n));LinkedList 随机访问慢(O (n))、增删快(O (1),只需改指针)。
场景:ArrayList 适合读多写少、需要随机访问;LinkedList 适合写多(首尾操作)、无需随机访问。

Q3:ConcurrentHashMap 如何保证线程安全?JDK 1.7 和 1.8 有什么区别?
A:JDK1.7:分段锁(Segment 数组,每个 Segment 是 ReentrantLock,锁粒度大,并发度 = Segment 数量);
JDK1.8:取消 Segment,用synchronized+CAS (锁链表头 / 红黑树根节点,锁粒度小,并发度更高)。

Q1:synchronized 和 volatile 的区别?
A:①synchronized:保证原子性、可见性、有序性(重量级锁,可重入);②volatile:仅保证可见性(禁止指令重排序),不保证原子性。
场景:synchronized 适合复合操作(如 i++),volatile 适合单一线程写、多线程读的场景(如状态标记)。

Q2:线程池的核心参数?如何设置合理的核心线程数?
A:核心参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(非核心线程空闲时间)、workQueue(任务队列)、handler(拒绝策略)。
线程数设置:①CPU 密集型(如计算):线程数≈CPU 核心数 + 1;②IO 密集型(如网络 / 数据库操作):线程数≈CPU 核心数 ×2(或根据 IO 阻塞时间调整)。

Q3:ThreadLocal 的原理?为什么会导致内存泄漏?
A:原理:每个 Thread 有 ThreadLocalMap,key 是 ThreadLocal(弱引用),value 是存储的值。作用是线程隔离 (每个线程存自己的副本)。
内存泄漏:ThreadLocalMap 的 key 是弱引用,GC 时 key 会被回收,但 value 仍被 Thread 引用(强引用),若 Thread 长期存活(如线程池),value 无法回收,导致泄漏。解决:使用后调用remove()手动清理。

Q1:BIO、NIO、AIO 的区别?
A:①BIO(同步阻塞):一个连接一个线程,效率低,适合连接少的场景;②NIO(同步非阻塞):基于 Selector、Channel、Buffer,一个线程管理多个连接,非阻塞,适合高并发(如 Netty);③AIO(异步非阻塞):操作完成后由 OS 通知线程,无需轮询,适合 IO 密集型但连接数不多的场景(如文件读写)。

Q2:NIO 的三大核心组件是什么?
A:①Channel(通道):双向读写(与 BIO 的 Stream 单向不同),如 FileChannel、SocketChannel;②Buffer(缓冲区):数据容器,Channel 读写必须通过 Buffer;③Selector(选择器):单线程监听多个 Channel 的事件(如连接、可读、可写),实现多路复用。

Q1:Lambda 表达式的作用? functional interface 是什么?
A:Lambda 简化匿名内部类代码(如(a,b)->a+b),本质是 "可传递的代码块"。
functional interface 是只有一个抽象方法的接口 (可含默认方法),是 Lambda 的载体(如 Runnable、Consumer)。

Q2:Stream API 的优势?常用操作有哪些?
A:优势:简化集合操作(链式调用),支持并行处理(parallelStream())。
常用操作:①中间操作(filter、map、sorted);②终止操作(collect、forEach、count)。

Q1:单例模式的实现方式?如何保证线程安全?
A:常见方式:①饿汉式(类加载时初始化,线程安全但可能浪费内存);②懒汉式(双重校验锁 + volatile,volatile防止指令重排序);③静态内部类(延迟加载,线程安全)。
示例(双重校验锁):

java

public class Singleton {

private static volatile Singleton instance;

private Singleton() {}

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton();

}

}

}

return instance;

}}

Q2:代理模式的两种实现?Spring AOP 用的哪种?
A:①静态代理:手动编写代理类,编译期生成;②动态代理:运行时生成代理类(JDK 动态代理基于接口,CGLIB 基于继承)。
Spring AOP:默认用 JDK 动态代理(目标类有接口时),无接口时用 CGLIB。

Q1:IoC 和 DI 的区别?
A:IoC(控制反转)是思想:对象创建权由自己转交给 Spring 容器;DI(依赖注入)是 IoC 的实现:容器在创建对象时,自动将依赖注入到对象中(如 @Autowired)。

Q2:AOP 的原理?常用场景有哪些?
A:AOP(面向切面)通过动态代理在目标方法前后插入增强逻辑(如日志、事务),核心概念:切面(Aspect)、通知(Advice)、切点(Pointcut)。
场景:日志记录、事务管理、权限校验。

Q3:Spring 事务的传播机制和隔离级别?
A:传播机制:定义多事务方法调用时的行为(如 REQUIRED:当前有事务则加入,无则新建;REQUIRES_NEW:无论是否有事务,都新建)。
隔离级别:①READ_UNCOMMITTED(读未提交);②READ_COMMITTED(读已提交,解决脏读);③REPEATABLE_READ(可重复读,解决不可重复读,MySQL 默认);④SERIALIZABLE(串行化,解决幻读)。

2. MyBatis

Q1:MyBatis 的一级缓存和二级缓存?
A:一级缓存:SqlSession 级别的缓存,默认开启,同一个 SqlSession 内多次查询相同 SQL 会缓存结果,关闭 SqlSession 后失效;
二级缓存:Mapper 级别的缓存,需手动开启(<cache/>),不同 SqlSession 可共享,查询前先查二级缓存→一级缓存→数据库。

Q2:MyBatis 接口绑定的方式?
A:①XML 映射文件(namespace 对应接口全类名,id 对应方法名);②注解(如 @Select、@Insert 直接写在接口方法上)。

1. MySQL

Q1:索引的类型?B + 树索引和哈希索引的区别?
A:索引类型:主键索引、二级索引(普通索引)、联合索引、唯一索引。
区别:B + 树索引支持范围查询、排序,适合频繁范围查询;哈希索引等值查询快(O (1)),但不支持范围查询、排序,适合高频等值查询(如字典表)。

Q2:事务的 ACID 特性?MySQL 如何保证?
A:ACID:原子性(Atomicity,事务要么全成要么全败,靠 undo log)、一致性(Consistency,最终状态合法,靠其他三特性保证)、隔离性(Isolation,靠锁和 MVCC)、持久性(Durability,靠 redo log)。

Q3:如何优化慢 SQL?
A:①加索引(避免全表扫描);②避免索引失效(如函数操作索引列、用!=、not in);③分页优化(limit 大偏移量时用子查询定位起点);④分表分库(大表拆分)。

2. Redis

Q1:Redis 的数据结构及应用场景?
A:①String(缓存、计数器);②Hash(存储对象,如用户信息);③List(消息队列、最新列表);④Set(去重、交集并集,如共同好友);⑤SortedSet(排序,如排行榜)。

Q2:缓存三大问题(穿透、击穿、雪崩)及解决方案?
A:①穿透(查不存在的数据,直击 DB):布隆过滤器拦截无效 key,或缓存空值;②击穿(热点 key 失效,瞬间大量请求击 DB):互斥锁(同一时间只让一个线程更新缓存),或热点 key 永不过期;③雪崩(大量 key 同时失效,DB 压力骤增):过期时间加随机值(错开失效时间),或集群部署(主从 + 哨兵)。

项目经验与场景题

1. 项目描述技巧

  • 用 "STAR 法则":S(场景)→T(任务)→A(行动,重点说自己负责的模块和技术难点)→R(结果,如性能提升多少、用户量增长)。
  • 例:"在仿微信聊天项目中(S),我负责消息实时推送模块(T),用 Netty 实现长连接,通过 Redis 缓存离线消息,解决了高并发下消息延迟问题(A),最终支持 10 万用户同时在线,消息投递成功率 99.9%(R)"。

2. 场景题

  • Q:如何设计一个高并发的订单系统?
    A:①限流(用 Redis+Lua 脚本做接口限流,防止过载);②异步处理(订单创建后用 MQ 发送消息,异步处理支付、物流,提高响应速度);③分库分表(按用户 ID 哈希分库,订单表按时间分表);④缓存(热点订单缓存,减少 DB 查询);⑤分布式锁(防止超卖,用 Redis 的 setnx 或 ZooKeeper)
相关推荐
测试老哥3 小时前
接口测试的测试用例应该怎么写?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
CC数分4 小时前
2026年HRBP岗位硬性要求和加分项
面试·职场和发展·数据分析
2601_962680224 小时前
数据分析面试常考的SQL题和业务题分别是哪几类?
sql·面试·数据分析
黄敬峰5 小时前
一文搞懂 Agentic RAG:用 LangGraph 打造会思考的智能检索架构
面试
晚安日记wanna6 小时前
SSR 为什么不适合登录态从水合冲突到缓存串号
前端·react.js·面试
晚安日记wanna6 小时前
压测 TPS 卡在 800CPU 只跑四成六步定位法
运维·面试·测试
晚安日记wanna6 小时前
批量请求失败只弹一个 Toast面试官想听五层
前端·面试·架构
晚安日记wanna6 小时前
TS const 类型参数一道面试题的四层追问
前端·面试·typescript
晚安日记wanna6 小时前
大表 DDL 面试翻车现场Online DDL 为什么还会锁死业务
数据库·面试·架构
晚安日记wanna6 小时前
MySQL 主从延迟别只答并行复制
数据库·面试·架构