CPU 飙高该如何排查
CPU 飙高排查我一般分三步:
第一:确认是用户态还是系统态高,用 top 看 us/sy/wa
第二:定位具体进程,再定位线程
第三:结合线程栈分析是死循环、锁竞争、GC 频繁还是线程过多
1)us 高、sy 低、wa 低
含义:纯用户态计算,无阻塞、无系统调用、无 IO
典型原因
- 死循环
- 复杂计算 / 递归
- JSON / 序列化疯狂
- 正则回溯爆炸
- GC 线程疯狂(VM Thread、GC task)
栈特征:大量 RUNNABLE,一直占 CPU 不释放
一句话:
us 高 sy 低 = 业务代码死循环 / 计算密集 / GC 频繁,直接 jstack 找 RUNNABLE 栈。
2)sy 高、us 低 / 一般
含义:内核态繁忙,系统调用频繁
典型原因
- 线程频繁切换(thread count 极高)
- 大量网络 IO:accept/read/write 太多
- 大量锁竞争(mutex、自旋锁)
- 大量小 IO、频繁系统调用
栈特征:
- RUNNABLE 但在native 方法
epollWait、read、write、lock- 大量线程 WAITING / BLOCKED
一句话:
sy 高 = 线程太多、切换频繁、锁竞争、网络 IO 密集,看线程数 + 锁。
3)wa 高(iowait 高)、us/sy 都不高
含义:CPU 空闲,但在等磁盘 IO
典型原因
- 磁盘满、磁盘慢
- 大量日志打印、文件读写
- SQL 慢查询(大量物理 IO)
- 大量阻塞 IO(InputStream、FileWriter)
栈特征:
- 大量 RUNNABLE 但卡在 IO
read、write、FileInputStream- 数据库驱动
socketRead0
一句话:
wa 高 = 不是 CPU 问题,是 IO 瓶颈:磁盘慢 / 日志多 / 慢 SQL。
4)锁竞争严重(sy 略高、us 一般、线程 BLOCKED 多)
特征:
- 锁等待多,CPU 不极端高,但应用极慢
BLOCKED大量出现- 大量线程等待同一把锁:
waiting to lock <0x...>
典型原因:synchronized 竞争、ReentrantLock 抢锁严重
一句话:
大量 BLOCKED = 锁冲突,找占有锁的线程,优化锁粒度或无锁。
5)GC 频繁导致 CPU 飙高
特征:
- us 高,但不是业务线程
- jstack 看到:VM ThreadGC task thread#0
- jstat -gc 看到 YGC 每秒多次、FGC 频繁
原因:内存不足、大对象、内存泄漏
一句话:
GC 线程占 CPU = 内存问题,不是业务代码死循环。
6)线程数过多导致 CPU 高
特征:
- sy 明显高
ps -eLf | grep java | wc -l几千线程- 大量 TIMED_WAITING、WAITING
- 频繁线程切换消耗内核 CPU
原因:线程池无限制、new Thread 滥用、定时任务太多
一句话:
线程数过多 → sy 高、吞吐低,限制线程池核心线程数。
三、终极面试万能口诀(背这个就行)
- us 高:死循环、计算密、GC 疯
- sy 高:线程多、切换频、锁竞争
- wa 高:IO 慢、磁盘忙、慢查询
- BLOCKED 多:锁冲突
- GC 线程高:内存炸
- 线程几千:池无限
查看6道真题和解析