🔹 Java 基础
1. HashMap 的底层结构?JDK 1.8 有什么变化?
答案:
-
JDK 1.7:数组 + 链表,链表头插法
-
JDK 1.8:
-
数组 + 链表/红黑树(链表长度 > 8 且数组长度 ≥ 64 时转为红黑树)
-
链表尾插法(解决多线程下可能的循环链表问题)
-
扩容时重新计算hash的方式优化(高位参与运算)
-
新增方法:
getOrDefault
、computeIfAbsent
等
-
2. synchronized 和 ReentrantLock 的区别?
答案:
特性 | synchronized | ReentrantLock |
---|---|---|
实现层面 | JVM层面 | JDK层面 |
锁的获取 | 自动获取释放 | 手动lock/unlock |
响应中断 | 不支持 | 支持lockInterruptibly() |
公平锁 | 非公平 | 可选择公平/非公平 |
条件变量 | 一个Condition | 多个Condition |
性能 | 优化后差距不大 | 高竞争下有优势 |
3. 什么是 volatile 关键字?它能保证原子性吗?
答案:
-
作用:
-
保证可见性:一个线程修改后,其他线程立即可见
-
禁止指令重排序
-
-
不能保证原子性 :如
count++
这种复合操作不是原子的 -
使用场景:状态标志位、DCL单例模式
4. 谈谈你对 JVM 内存模型的理解?
答案:
-
线程私有:
-
程序计数器:当前线程执行的字节码行号
-
虚拟机栈:方法执行的内存模型
-
本地方法栈:Native方法服务
-
-
线程共享:
-
堆:对象实例分配区域
-
方法区:类信息、常量、静态变量
-
-
JDK 1.8:元空间替代永久代
5. 什么是双亲委派模型?为什么要使用它?
答案:
-
工作机制:类加载请求先委派给父加载器,只有父加载器无法完成时才自己加载
-
层次结构:
-
Bootstrap ClassLoader
-
Extension ClassLoader
-
Application ClassLoader
-
自定义ClassLoader
-
-
优点:
-
避免类的重复加载
-
保证核心类库安全(如java.lang.Object)
-
🔹 Spring & Spring Boot
1. Spring Boot 自动装配的原理是什么?
答案:
-
核心注解 :
@SpringBootApplication
→@EnableAutoConfiguration
-
关键文件 :
META-INF/spring.factories
-
流程:
-
扫描
spring.factories
中的EnableAutoConfiguration
配置 -
通过
@Conditional
条件判断决定是否装配 -
创建并注册Bean到IOC容器
-
2. Spring 中 Bean 的生命周期?
答案:
-
实例化Bean
-
属性赋值(依赖注入)
-
调用Aware接口方法(BeanNameAware、BeanFactoryAware)
-
BeanPostProcessor前置处理
-
初始化方法(@PostConstruct、InitializingBean)
-
BeanPostProcessor后置处理
-
Bean就绪使用
-
容器关闭时调用销毁方法(@PreDestroy、DisposableBean)
3. Spring 事务传播机制有哪些?如何使用?
答案:
-
REQUIRED(默认):有事务加入,无事务新建
-
REQUIRES_NEW:新建事务,挂起当前事务
-
NESTED:嵌套事务,外部事务回滚会影响内部
-
SUPPORTS:有事务就用,没有就算了
-
NOT_SUPPORTED:非事务执行,挂起当前事务
-
MANDATORY:必须有事务,否则抛异常
-
NEVER:必须无事务,否则抛异常
4. Spring MVC 的工作流程是怎样的?
答案:
-
用户请求 → DispatcherServlet
-
DispatcherServlet 查询 HandlerMapping
-
调用 HandlerAdapter 执行 Controller
-
Controller 返回 ModelAndView
-
视图解析器解析视图
-
渲染视图并返回响应
5. 如何自定义一个 Starter?
答案:
// 1. 创建配置类
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() {
return new MyService();
}
}
// 2. 在META-INF/spring.factories中配置
// org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyAutoConfiguration
🔹 数据库 & Redis
1. MySQL 索引底层结构?什么是聚簇索引?
答案:
-
底层结构:B+Tree
-
聚簇索引:
-
索引与数据存储在一起
-
InnoDB主键就是聚簇索引
-
一个表只有一个聚簇索引
-
-
非聚簇索引:
-
索引与数据分离
-
叶子节点存储主键值,需要回表查询
-
2. 什么是事务的隔离级别?MySQL 默认是哪个?
答案:
-
读未提交:可能脏读、不可重复读、幻读
-
读已提交:解决脏读(Oracle默认)
-
可重复读:解决脏读、不可重复读(MySQL默认)
-
串行化:解决所有问题,性能最低
3. Redis 持久化方式有哪些?区别是什么?
答案:
-
RDB:
-
定时快照,文件小,恢复快
-
可能丢失最后一次快照后的数据
-
-
AOF:
-
记录所有写操作,数据安全
-
文件大,恢复慢
-
-
混合持久化(Redis 4.0+):RDB + AOF,兼顾速度和数据安全
4. 如何用 Redis 实现分布式锁?要注意什么?
答案:
-- 加锁
SET lock_key unique_value NX EX 30
-- 解锁(Lua脚本保证原子性)
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
注意事项:
-
设置唯一value,防止误删其他线程的锁
-
设置过期时间,避免死锁
-
考虑锁续期问题
5. 缓存穿透、缓存雪崩、缓存击穿有什么区别?如何解决?
答案:
-
缓存穿透:查询不存在的数据
- 解决:布隆过滤器、缓存空对象
-
缓存雪崩:大量缓存同时失效
- 解决:设置不同的过期时间、集群部署
-
缓存击穿:热点key突然失效
- 解决:永不过期、互斥锁重建
🔹 微服务 & 分布式
1. 什么是服务注册与发现?Nacos 和 Eureka 有什么区别?
答案:
-
服务注册:服务提供者向注册中心注册自身信息
-
服务发现:服务消费者从注册中心获取服务列表
-
区别:
-
Nacos支持CP+AP模式切换,Eureka只支持AP
-
Nacos支持配置管理,Eureka不支持
-
Nacos健康检查更丰富
-
2. 如何保证微服务之间的调用安全?
答案:
-
使用HTTPS加密传输
-
JWT Token身份认证
-
API网关统一鉴权
-
服务间认证(如Spring Security OAuth2)
3. 什么是熔断和降级?Sentinel 是如何实现的?
答案:
-
熔断:服务故障时快速失败,避免雪崩
-
降级:服务压力大时关闭非核心功能
-
Sentinel实现:
-
基于滑动窗口统计QPS、响应时间等指标
-
根据规则进行流量控制、熔断降级
-
4. 你了解 Spring Cloud Gateway 的过滤器吗?如何使用?
答案:
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-color, blue
- PrefixPath=/api
-
全局过滤器:对所有路由生效
-
局部过滤器:对特定路由生效
🔹 项目 & 场景题
1. 你在项目中遇到的最大技术难点是什么?如何解决的?
参考答案 :
"在博客系统的评论模块中,需要实现多级评论回复。最初使用递归查询,但性能很差。后来改用parent_id
字段维护层级关系,结合tree_path
字段存储评论路径,通过一次SQL查询获取所有评论,在内存中构建树形结构,性能提升了10倍以上。"
2. 如果系统出现 CPU 飙高,如何排查?
答案:
-
top
命令找到占用CPU高的进程 -
top -Hp <pid>
找到具体线程 -
jstack <pid> > stack.log
导出线程栈 -
将线程ID转换为16进制,在stack.log中查找对应线程
-
分析代码定位问题(如死循环、频繁GC等)
3. 如何设计一个秒杀系统?
答案:
-
前端:静态化页面、按钮防重复点击
-
网关:限流、恶意请求过滤
-
服务层:
-
Redis预减库存(原子操作)
-
消息队列异步处理订单
-
令牌桶限流
-
-
数据层:数据库乐观锁、分库分表
4. 你如何保证接口的幂等性?
答案:
-
Token机制:先获取token,请求时携带token
-
唯一索引:防重复提交
-
状态机:只有特定状态才能执行操作
-
分布式锁:防并发重复提交
-
悲观锁/乐观锁:数据库层面控制