java程序线上运行时,出现cpu过高的情况如何进行定位呢?
记得刚参加工作的时候,老同事留下的一个项目,出现了cpu100%的情况,后来检查代码发现,之前的同事在写这块的时候,没有考录到多线程并发的问题,有个定时器偶发的多线程情况下同时写入同一个hashmap,导致cpu爆表
我们写一个小demo进行演示
首先准备一段java示例代码:
public class Test{
public static void main(String args[]){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true){
System.out.println(i++);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.setName("mytest");
thread.start();
}
新启了一个线程,每10毫秒输出自增的数,在1c1g的机器上已经能体现出来消耗了
准备好Test.java文件,
使用javac Test.java命令编译java代码;
使用nohup java Test &启动java进程;
使用tail -f nohup.out已经能看到程序的输出了
我们可以去定位这个耗费资源比较大的线程了;
首先使用top -H命令
持续观察可以看到3624这个线程一直处在占用cpu的状态,这里时间间隔10ms负载并不大,所以占用的不多,不过已经可以展示了
使用jps命令查看当前系统中运行的java进程
使用printf %x 3624 获取3624这个线程的16进制数,因为java的线程id都是使用十六进制数表示的
获得了e28这个id
下来使用jstack 3614打印jvm的堆栈信息
由于程序比较简单,打印出来的内容就这么多,我们在堆栈信息中找到e28这个线程对应的信息,
可以看到,这个线程整处于sleep状态,
这样我们就能找对问题的地方,去排查问题了