CPU 使用率较高排查和解决
Java 应用 CPU 使用率过高(如持续超过 80%)会导致应用响应缓慢、服务器负载过高,核心排查思路是 “找到占用 CPU 的线程和代码,优化性能瓶颈”,具体步骤如下:
# 1. 第一步:定位占用 CPU 的进程和线程
- 找到高 CPU 进程:执行
top命令(Linux),找到 CPU 使用率高的 Java 进程(PID); - 找到进程内高 CPU 线程:执行
top -Hp <PID>,找到该进程内 CPU 使用率高的线程(TID); - 转换线程 ID 为十六进制:执行
printf "%x\n" <TID>,将线程 ID 转为十六进制(用于后续 jstack 分析)。
# 2. 第二步:获取线程堆栈,定位问题代码
- 生成线程堆栈:执行
jstack <PID> > thread_dump.txt,生成线程堆栈文件; - 查找高 CPU 线程的堆栈:在 thread_dump.txt 中搜索十六进制线程 ID(忽略大小写),找到对应的线程堆栈;
- 分析堆栈信息:
- 若线程状态为
RUNNABLE,且堆栈显示在自定义代码(如com.example.service.UserService.process()),说明该代码存在性能瓶颈(如死循环、频繁循环、复杂计算); - 若线程状态为
WAITING/BLOCKED,可能是线程竞争锁导致(如大量线程等待同一把锁)。
- 若线程状态为
# 3. 第三步:针对性解决问题
- 场景 1:代码逻辑导致(死循环、频繁计算)
- 排查代码:找到堆栈对应的方法,检查是否有死循环(如
while(true)无终止条件)、频繁循环(如遍历百万级集合)、复杂计算(如嵌套循环); - 优化方案:修复死循环、分批处理大数据、优化算法(如 O (n²) 改为 O (n log n))。
- 排查代码:找到堆栈对应的方法,检查是否有死循环(如
- 场景 2:线程竞争锁导致
- 排查锁竞争:通过
jstack查看锁持有线程和等待线程,找到竞争激烈的锁(如synchronized修饰的高频方法); - 优化方案:减少锁粒度(如用
ReentrantLock替代synchronized,或拆分锁对象)、使用无锁并发(如Atomic类、ConcurrentHashMap)、避免频繁加锁(如缓存热点数据)。
- 排查锁竞争:通过
- 场景 3:GC 频繁导致
- 排查 GC:执行
jstat -gc <PID> 1000,查看 GC 频率和时间,若 YGC/FGC 频繁,导致 CPU 使用率高; - 优化方案:调整 JVM 参数(如增大堆内存、调整新生代比例)、排查内存泄漏、优化对象创建(减少大对象)。
- 排查 GC:执行
- 场景 4:第三方组件导致
- 排查组件:若堆栈显示在第三方库(如数据库驱动、缓存客户端),可能是第三方组件存在性能问题(如数据库查询慢、缓存连接池耗尽);
- 优化方案:优化数据库查询(如添加索引)、调整连接池参数(增大连接数)、更换高性能组件。
# 4. 第四步:长期优化与监控
- 代码优化:定期进行代码审查,避免死循环、低效算法、过度锁竞争;
- 性能测试:上线前通过压测模拟高负载,提前发现 CPU 瓶颈;
- 监控告警:监控 CPU 使用率、线程状态、GC 频率,超过阈值及时告警;
- 定期复盘:分析 CPU 高使用率案例,总结优化经验,避免同类问题。
上次更新: 12/30/2025