排查cpu高需分三层:先看top头部%cpu(s)判断瓶颈类型(us/us/sy/wa等),再用top -h或ps定位高耗线程,最后用jstack/pstack/gdb结合十六进制tid定位代码行。

别一看到 CPU 高就 kill -9,真正的问题往往藏在线程和代码里。排查要分三层:先看全局负载类型,再锁住具体进程和线程,最后落到函数或代码行。
看懂 top 头部的 CPU 分类,判断真实瓶颈
执行 top 后,第一眼不是扫进程列表,而是看顶部的 %Cpu(s) 行:
- us(用户态)高 → 业务代码在忙,比如 Java/Python 服务死循环、正则爆炸、日志狂打
- sy(内核态)高 → 系统调用频繁,可能是锁竞争、内存分配过载、驱动异常
- wa(I/O 等待)高 → CPU 其实在空等磁盘,不是算力问题,杀进程没用
- si/hi(软/硬中断)高 → 检查网卡收包、存储中断、是否遭遇中断风暴
- st(steal 时间)高 → 虚拟机被宿主机“偷”了 CPU,得联系云平台或检查同宿主邻居
快速定位高 CPU 进程和线程
确认是 us 高后,再往下走:
- 按 P 键确保 top 按 %CPU 排序,记下最靠前的 PID
- 用 top -H -p [PID] 切换到线程视图,找 TID(线程 ID)最高的那个
- 或用更轻量命令一次性筛选:
ps -mp [PID] -o THREAD,tid,time | sort -rn | head -5 - 把高耗线程的 TID 转成十六进制:
printf "%x\n" [TID](例如 3626 → e18)
用 jstack 或 pstack 定位到具体代码位置
适用于 Java 进程(jstack)或通用进程(pstack):
- 对 Java 应用:
jstack [PID] | grep -A 20 "[十六进制TID]"
例如 jstack 2633 | grep -A 30 "e18",输出中栈顶方法就是热点 - 对非 Java 进程:
pstack [PID] 查所有线程调用栈,找到对应 TID 的那一段,看最上面的函数名 - 若 pstack 不可用,可用 gdb 快速抓栈:
gdb -p [PID] -ex "thread [TID]" -ex "bt" -ex "quit"
辅助验证与长期监控建议
单次排查完别停步,补上两件事:
- 用 pidstat -u 1 或 vmstat 1 持续观察 30 秒,确认高 CPU 是偶发还是持续
- 部署基础告警:Zabbix/Nagios 或阿里云监控配置 us > 70% 持续 2 分钟触发通知
- 线上可直接跑现成脚本:
show-busy-java-threads.sh(oldratlee 开源),一步完成进程→线程→堆栈定位











