列举 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