CPU飙高问题如何排查3
线上系统CPU飙高问题可以按以下步骤排查
1、确定问题进程
首先,使用 top 命令找出占用 CPU 较高的 Java 进程:
top
找到对应的进程 ID(PID)。

2、获取线程信息
使用 top -Hp 命令查看该进程内各个线程的 CPU 占用情况:
top -Hp <PID>
记录下占用CPU较高的线程ID

3、转换线程 ID 为十六进制
使用 printf 命令将线程 ID 19664 转换为十六进制,结果为 0x4cd0:
printf "%x\n" <线程ID>
4、获取线程堆栈
使用 jstack 命令获取进程的线程堆栈信息,并过滤出指定线程(4cd0)附近的堆栈内容:
# 得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致CPU飙高的调用方法
jstack 19663 | grep -A 10 4cd0

5、代码分析
根据堆栈信息,查看相关的 Java 代码。以下是一些可能导致 CPU 飙高的代码示例:
示例 1:死循环
while (true) {
// 耗 CPU 的操作
}
示例 2:频繁的垃圾回收(GC)
List<Object> list = new ArrayList<>();
while (true) {
list.add(new Object());
if (list.size() > 10000) {
list.clear();
}
}
示例 3:不当的线程同步(死锁风险)
public class BadSynchronization {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void method1() {
synchronized (lock1) {
synchronized (lock2) {
// 操作
}
}
}
public static void method2() {
synchronized (lock2) {
synchronized (lock1) {
// 操作
}
}
}
}
说明:method1 先锁定 lock1 再锁定 lock2,而 method2 先锁定 lock2 再锁定 lock1,多线程并发调用时可能产生死锁,导致线程阻塞或频繁上下文切换,进而引起 CPU 飙高。
6、使用性能分析工具
可以使用诸如 Arthas、JProfiler 等 Java 性能分析工具进行更深入的分析。
7、查看 GC 日志
如果怀疑是 GC 问题,可以查看 GC 日志:
jstat -gcutil <PID> 1000
8、检查系统资源
使用 vmstat、iostat 等命令检查系统资源使用情况,排除是否为系统资源问题。
# 查看系统整体资源使用情况
vmstat 1
# 查看磁盘 I/O 情况
iostat -x 1
总结
通过以上步骤,我们可以定位到导致 CPU 飙高的具体代码位置,然后进行相应的优化。常见的优化方法包括:
-
优化算法
-
增加缓存
-
调整线程池参数
-
优化数据库查询

浙公网安备 33010602011771号