北京小厂 Java 一面:线程池、联合索引与 Spring 事务失效
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 自我介绍。
- 介绍一下你的一个项目(agent 代码平台),说一下你印象深刻的问题和解决方法。
- 创建线程的方法有哪些?
- 自定义线程池了解吗?
- 能不能介绍一下线程池的参数?
- 一个任务被提交给线程池的流程是怎样的?拒绝策略有哪些?
- 介绍一下 JVM 的内存区域。
- 堆被细分为哪些区域?
- 垃圾回收算法了解吗?
- MySQL 的索引有哪些?
- 联合索引 a,b,c,d 四个字段,条件为 a=1,b=2,d>6,c=5,使用了联合索引的哪些字段?查询顺序影响索引结果吗?
- Spring Boot 自动装配原理是什么?
- Redis 的持久化机制,两种方法各有什么优缺点?
- Spring 怎么使用事务?
- Spring 事务什么时候失效?
- 项目启动的时候要做一些特殊的逻辑处理,比如扫描某张表,怎么去做?
- @PostConstruct 有什么用?知道吗,用过吗?
- 反问:面试改进建议、业务范围。
《参考解析》
线程池七参数与提交流程:核心线程数、最大线程数、空闲存活时间、时间单位、工作队列、线程工厂、拒绝策略。任务提交后先看核心线程是否满,未满则新建核心线程;满了进队列;队列满了再扩到最大线程数;仍满则触发拒绝策略——AbortPolicy 抛异常、CallerRunsPolicy 由提交线程执行、DiscardPolicy 静默丢弃、DiscardOldestPolicy 丢队首。回答时补一句「队列长度和最大线程数要一起看,无界队列会让 maximumPoolSize 形同虚设」会更扎实。
联合索引 a,b,c,d 那题:条件是 a=1、b=2、c=5 三个等值加 d>6 一个范围,最左前缀可以一路用到 c,d 用索引下推或范围扫描过滤,四列都能参与;SQL 里条件的书写顺序由优化器重排,不影响执行计划。要记住的规则是「范围条件之后的列无法继续用于索引定位」,这里 d>6 恰好是最后一列,所以不受影响。
JVM 内存与堆划分:线程私有的是程序计数器、虚拟机栈、本地方法栈;线程共享的是堆和方法区(JDK 8 之后是元空间,位于本地内存)。堆按分代分为新生代(Eden 与两块 Survivor)和老年代,默认比例 8:1:1,比例可调的目的是让存活对象尽快进入老年代,减少复制开销。
Redis 持久化:RDB 是某一时刻的全量快照,文件紧凑、恢复快,但两次快照之间的数据会丢,fork 时也可能阻塞;AOF 追加写命令,按 everysec 配置最多丢一秒,文件大、恢复慢,支持重写压缩。生产上常见是两者同开,用 RDB 做冷备、AOF 保证丢数据窗口。
Spring 事务失效的典型场景:同类内部方法直接调用(绕过代理)、方法不是 public、异常被 catch 掉或抛的是受检异常而没配 rollbackFor、事务方法被 final 修饰、多线程里执行、Bean 没有被 Spring 管理、数据库引擎不支持事务。用 @Transactional 时最好显式写明 rollbackFor 和传播行为。
启动时做初始化逻辑的几种写法:@PostConstruct(依赖注入完成后执行一次,适合本 Bean 的初始化)、实现 InitializingBean 的 afterPropertiesSet、实现 ApplicationRunner 或 CommandLineRunner(容器启动完成后执行,能拿到启动参数)、监听 ApplicationReadyEvent。扫表这类重活更适合放在 Runner 里,避免拖慢容器启动。