1. 模拟
不断的运算,会造成cpu使用率的飙升。所以我们需要在Java程序中做运算,一个线程有可能飚不到很高,所以我们启动了10个线程。
@RequestMapping("/main")
public class MainController {
private static volatile boolean exit= true;
@RequestMapping("/start")
public void start() {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i =0;i<10;i++){
executorService.submit(() -> {
int k = 0;
while (MainController.exit){
k++;
}
});
}
}
@RequestMapping("/stop")
public void stop() {
exit = false;
}
}
2. 部署服务器
部署到服务器上,启动工程
3. 访问服务
http://192.168.52.200:8881/main/start
3.1 TOP查看
直接看到第一行,CPU的使用率已经达到了99%,接下来我们开始排查具体是什么导致的。假设我们现在对项目具体代码不清楚。
3.2 拿到线程ID
这里我们从图上可以直接看到,PID = 32008
3.3 根据进程找到该进程下线程的CPU使用情况
ps -mp 32008 -o THREAD,tid,time | sort -rn
或者
top -H -p 32008
结果,我们以第一种为例,可以看到占用CPU高的线程全部打印了出来。到此,我们先以tid为32043为例子。
3.4 将TID转换为16进制
因为在线程信息中,我们要找到这个线程,他都是一16进制表示ID的,所以我们先转化一下。
printf "%x\n" tid
结果
3.5 根据线程ID查找信息
jstack pid |grep 7d2b -A 30
结果,我们可以看到这个方法的调用栈了,至此我们应该知道到底是哪里出了问题。
"pool-1-thread-10" #36 prio=5 os_prio=0 tid=0x00007f9c30005800 nid=0x7d2b runnable [0x00007f9c256d0000]
java.lang.Thread.State: RUNNABLE
at com.example.yunwei.MainController.lambda$start$0(MainController.java:25)
at com.example.yunwei.MainController$$Lambda$460/835609887.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"pool-1-thread-9" #35 prio=5 os_prio=0 tid=0x00007f9c30004000 nid=0x7d2a runnable [0x00007f9c257d1000]
java.lang.Thread.State: RUNNABLE
at com.example.yunwei.MainController.lambda$start$0(MainController.java:25)
at com.example.yunwei.MainController$$Lambda$460/835609887.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"pool-1-thread-8" #34 prio=5 os_prio=0 tid=0x00007f9c30002800 nid=0x7d29 runnable [0x00007f9c258d2000]
java.lang.Thread.State: RUNNABLE
at com.example.yunwei.MainController.lambda$start$0(MainController.java:25)
at com.example.yunwei.MainController$$Lambda$460/835609887.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"pool-1-thread-7" #33 prio=5 os_prio=0 tid=0x00007f9c300d0000 nid=0x7d28 runnable [0x00007f9c259d3000]
4 总结
- Top命令查找PID
- 根据PID查找对应的TID
- 将TID转化为16进制方便查看
- 根据jstack命令查看该TID的调用栈信息。