首页 > 技术文章 > Java CPU 100% 场景复现与分析

kakacbing 2019-03-21 16:26 原文

列举 4 种 cpu 100% 的场景,之后会进行复现,以及对应的解决方案。

死循环

Java 代码

public class HelloWorld {
    public static void main(String[] args) {
        // 直接死循环
        new Thread(() -> { while (true){ } }).start();
    }
}

分析

  • top 分析进程使用资源情况

  • 执行 top -Hp 2581 可查看进程 2581 中的占用 CPU 的线程 ID 是 2592 。

  • 执行 16 进制的转换 printf "%x \n" 2592 得到 a20 的,再通过 jstack 命令定位出现问题的地方

大量 Full GC

Java 代码

public static void main(String[] args) {
   //-XX:+UseSerialGC -Xms200M -Xmx200M -Xmn32m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
    byte[] newErdo = new byte[1024 * 1024 * 30];

    while (true) {
        // 触发 full gc
        System.gc();
        byte[] bytes = new byte[1024 * 1024 * 120];
    }

}

分析

  • top 分析资源使用情况

  • 查看 gc 状态

线程计算耗时长

Java 代码

public static void main(String[] args) {
    // 有复杂,耗时长的计算,导致 CPU 100%
    work();
}

private static void work() {
    // 利用 CPU 计算 π 的近似值
    int i = Integer.MAX_VALUE;
    double pi, temp = 0;
    for (int j = 1; j <= i; j++) {
        temp += Math.pow(-1, j + 1) / (2 * j - 1);
    }
    pi = 4 * temp;
    System.out.println(pi);
}

分析

大量线程上下文切换

Java 代码

public static void main(String[] args) {
    // 大量线程 2000 同时并发,且进行等待
    for (int i = 0; i < 2000; i++) {
        new Thread(() -> {
            try {
                work();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
    System.out.println(1111111111);

}

private static void work() throws InterruptedException {
    Thread.sleep(10000L);
    System.out.println("----> do work now");
}

分析

类似上述案例一样,运行程序后,会发现 CPU 突然飙升~~~

总结

命令 汇总

top -Hp [pid]

printf "%x \n" [tid]

jstack [pid]|grep [16 进制 tid] -A 10

推荐阅读