CPU飙高问题如何排查3

线上系统CPU飙高问题可以按以下步骤排查


1、确定问题进程


首先,使用 top 命令找出占用 CPU 较高的 Java 进程:

top


找到对应的进程 ID(PID)。

Snipaste_2026-07-04_19-25-10


2、获取线程信息


使用 top -Hp 命令查看该进程内各个线程的 CPU 占用情况:

top -Hp <PID>

记录下占用CPU较高的线程ID

Snipaste_2026-07-04_19-32-05


3、转换线程 ID 为十六进制


使用 printf 命令将线程 ID 19664 转换为十六进制,结果为 0x4cd0

printf "%x\n" <线程ID>


4、获取线程堆栈


使用 jstack 命令获取进程的线程堆栈信息,并过滤出指定线程(4cd0)附近的堆栈内容:


# 得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致CPU飙高的调用方法
jstack 19663 | grep -A 10 4cd0

Snipaste_2026-07-04_19-38-02


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 飙高的具体代码位置,然后进行相应的优化。常见的优化方法包括:

  • 优化算法

  • 增加缓存

  • 调整线程池参数

  • 优化数据库查询

posted @ 2026-07-04 19:53  jock_javaEE  阅读(5)  评论(0)    收藏  举报