java 应用 cpu 过高故障排查

一、前言

前两天写了一个订阅消息队列程序传递到 Flink,将订阅到的每个数据添加到 Queue 队列中,使用了 while(true) 从消息队列取数据,程序能正常运行,后来发现 CPU 使用率过高,通过排查发现时 while(true) 引起的,现在模拟 cpu 过高排查过程。

二、测试代码 Test.java

public class Test {
    
    
    public static void main(String[] args) {
    
    
        System.out.println("测试死循环对 CPU 影响");
        for (int i = 0; i < Integer.parseInt(args[0]); i++) {
    
    
            new Thread(()->{
    
    
                System.out.println(Thread.currentThread().getName());
                while (true){
    
    

                }
            },"线程:"+i).start();
        }
    }
}

三、Linux 编译运行 Test.java 程序

javac Test.java

运行 Test 程序,启动 1 个死循环线程

在这里插入图片描述

四、top 命令查看 cpu 使用情况

按大写 C 可以按 CPU 从大到小排序
在这里插入图片描述

可以看到 Test 的 CPU 使用率 100%,和 window 区别很大(window CPU 100% 就卡死了),我的 Linux 服务器是 2 核的,总 CPU 使用率 50 %,服务器也不会卡,简单理解就是把一个核跑满了

五、查看进程下的线程详情 top -H -p 11748

如下可以看到进程 12227 下线程 12240 的 CPU 占用最多 99.9%
在这里插入图片描述

六、将线程 12240 的 pid 转为 16 进制 printf "0x%x\n" 12240

这一步的目的是从进程快照中检索线程
在这里插入图片描述

七、jstack 查看进程的快照

使用 java jdk 下自带的 jstack 查看进程的快照 jstack 12227|grep -A 20 0x2fd0
可以看到第 7 行代码引起的,从源代码可以看到是 while(true) 引起的,简单说一下 grep 参数

  • grep -A n 显示匹配指定内容及之后的 n 行

  • grep -B n 显示匹配指定内容及之前的 n 行

  • grep -C n 显示匹配指定内容及其前后各 n 行

在这里插入图片描述
输出整个进程的快照到文件 jstack 12227 >> jstack.log
在这里插入图片描述

遗留

当我把线程数量设为 2,发现 2 核 CPU 直接 100%,但云服务器并没有卡死
在这里插入图片描述
在这里插入图片描述
对于 Linux ,当我把线程数量设为大于 2 的数时,CPU接近 200%,应该只是会影响执行效率,不会导致系统卡死(猜的,操作系统知识都忘完了,等后面了解了再记录),下main是线程数量为 5 的情况
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41538097/article/details/131842679
今日推荐