Java并发编程面试题
线上服务CPU飙高,你如何排查?请描述完整的调优流程
总体思路采用 止血 ——> 定位 -> 分析 -> 修复 -> 发布验证 -> 复盘
止血
- 通过监控大盘,迅速是哪些节点的服务有问题;查看系统load、sys(上下文切换、锁竞争、频繁内核调用)、user(业务计算)、wait(io阻塞)
- 查看系统Load Average 是否远超CPU核数限制、结合vmsataus 1 5 查看 cs(上下切换)、si/so 交换内存、
- 紧急措施:网关限流/降级非核心链路、动态扩容,必要时摘除故障节点并重启
精确定位高CPU线程
1 | # ① 找高 CPU 进程 |
或者使用 arthas, thread -n 5 直接找出cpu过高的线程
原因分析
| 状态 | 典型原因 | 验证手段 |
|---|---|---|
| RUNNABLE | 死循环、复杂正则、大量计算、序列化/反序列化、频繁 Full GC | jstat -gcutil |
| BLOCK/WAITING | 线程锁竞争、连接池耗尽、同步 I/O 阻塞 | jstack 找 waiting to lock;检查 DB/Redis 慢查询或连接配置 |
| Sys CPU 占比高 | 频繁上下文切换、大量短连接、锁自旋、驱动/网络中断 | pidstat -w 1、sar -W 1、检查 net.core.somaxconn/tcp_tw_recycle |
修复 & 调优
代码层:修复死循环/正则、改用异步处理、优化算法复杂度、分页/流式导出。
JVM 层:调整 GC 参数(如 G1 MaxGCPauseMillis)、调大年轻代减少 Minor GC、排查内存泄漏。
架构层:日志改异步(Log4j2 AsyncAppender)、报表走离线数仓、引入缓存/读写分离。
验证 & 预防
灰度发布后观察 CPU/RT/QPS/错误率曲线。
补充监控告警:CPU 持续 >80% 超 3min 触发告警;配置线程池/连接池监控。
输出复盘报告:根因、影响面、改进项、压测基线。
其他
区分 Load Average 和 CPU Usage:Load 高不一定是 CPU 问题,可能是 D 状态进程(I/O 阻塞)。
提一嘴火焰图:async-profiler 或 Arthas profiler 生成火焰图,能直观看到 CPU 热点方法链,比纯看 jstack 更高效。
强调生产安全:线上不盲目 kill -3 或频繁 jstack,优先用 Arthas、pidstat、监控大盘无损排查。
闭环思维:排查不是目的,建立基线监控、压测标准、容量规划才是工程化价值。