衡泰技术 Java 后端一面:线程池、Kafka 有序性与 G1 调优
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 介绍线程池,项目中有哪些应用?淘汰策略为什么选这个?
- Kafka 中的消息有序性怎么保证?消费者多线程的情况下怎么处理消息有序性?
- Spring 中的 Bean 加载过程是怎样的?引入一个 jar 包,怎么知道要加载哪些东西?
- ClickHouse 的选型考虑,以及物化视图怎么用?
- G1 垃圾回收器和 CMS 有什么区别?
- DDD 架构怎么理解?
- 线上 CPU 飙高怎么排查?
《参考解析》
线程池与拒绝策略:先讲七个参数与提交流程:核心线程占满后入队,队列满才扩到最大线程,再满触发拒绝。CPU 密集型线程数接近核数,IO 密集型按等待/计算比放大;队列必须有界,否则堆积会拖爆内存。拒绝策略选自定义实现,记录日志并抛异常交上游重试,宁可快速失败也不静默丢任务,而不是 CallerRunsPolicy 把压力反弹回调用方。
Kafka 消息有序性:Kafka 只保证单分区内有序。生产者按业务 key(如订单号)分区,开启幂等 enable.idempotence=true 压掉重试乱序。消费侧一个分区同一时刻只由一个线程处理,要多线程消费就用「单线程拉取 + 按 key 哈希进内存队列 + 每队列固定线程」。扩并行度应增加分区与实例;跨分区全局有序只能牺牲吞吐,用单分区或消费后按序号重排。
Spring Bean 加载与自动装配:生命周期大致是实例化、属性填充、Aware 回调、BeanPostProcessor 前后处理、初始化、使用、销毁。引入 jar 后之所以知道加载什么,靠自动装配:Spring Boot 读取依赖的 META-INF/spring/...AutoConfiguration.imports(旧版 spring.factories)列出的配置类,再按 @ConditionalOnClass、@ConditionalOnMissingBean 等条件筛选,最后由 @ComponentScan 扫当前包。
线上 CPU 飙高排查:top 找进程,top -Hp 定位线程,线程号转十六进制后在 jstack 里对照 nid 找到栈顶,判断是死循环、频繁 GC 还是锁自旋。再看 jstat -gcutil 与 GC 日志,老年代居高不下就 jmap -histo 或堆 dump 找大对象;计算型热点用 async-profiler 或 arthas 的 profiler 拿火焰图。结合近期发布与流量确认根因,再决定回滚、限流或改代码。