线上Java程序占用CPU过高解决方案
这个问题可以说是 Java 面试的高频面试题了,有很多面试官都喜欢问这个问题,问题可能是下面这样的。
线上一台服务器 CPU 使用率100% 了,如果你碰到这样的情况,如何排查并找到问题原因?
这就是一个套路题,所谓套路题就是有标准的套路解法的,掌握了套路,不仅能解决面试官,还能解决问题。不然真的就掉进套路里了。
当我们真碰到这个问题的时候应该怎么排查呢?
模拟一个高 CPU 场景
先用一段程序创建几个线程,将其中一个线程设置成高 CPU 使用率的。
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(30 * 60 * 1000);
}catch (Exception e){
e.printStackTrace();
}
});
thread.setName("thread-" + i);
thread.start();
}
Thread highCpuThread = new Thread(() -> {
int i = 0;
while (true) {
i++;
}
});
highCpuThread.setName("HighCpu");
highCpuThread.start();
}
运行这段程序后,前面 10 个线程都处于休眠状态,只有最后一个线程会持续的占用 CPU 。
运行这段程序,然后就可以开始一些列的操作来发现问题原因了。
排查步骤第一步,使用 top 找到占用 CPU 最高的 Java 进程
在真实环境中,首先要确认是不是 Java 程序造成的,如果有系统监控工具,可能会直接在预警信息里告诉你是有哪个进程造成的,但也有可能不知道,需要我们手动排查。
如果是在面试场景中,这个问题可能不需要确认,毕竟 Java 面试,面试官可能直接就告诉你是 Java 占用的 CPU 过高。
这一步也非常简单,就是一个 top命令而已,基本上所有同学都用过这个命令吧。

使用 top命令发现占用 CPU 99.7% 的线程是 Java 进程,进程 PID 为 13731。
第二步,用 top -Hp 命令查看占用 CPU 最高的线程
上一步用 top命令找到了那个 Java 进程。那一个进程中有那么多线程,不可能所有线程都一直占着 CPU 不放,这一步要做的就是揪出这个罪魁祸首,当然有可能不止一个。
执行top -Hp pid命令,pid 就是前面的 Java 进程,我这个例子中就是 13731 ,完整命令为:
top -Hp 13731,执行之后的效果如下

可以看到占用 CPU 最高的那个线程 PID 为 13756。
然后将 13756转换为 16 进制的,后面会用到,可以用在线进制转换的网站直接转换,转换结果为 0x35bc
第三步,保存线程栈信息
当前 Java 程序的所有线程信息都可以通过 jstack命令查看,我们用jstack命令将第一步找到的 Java 进程的线程栈保存下来。
jstack 13731 > thread_stack.log
第四步,在线程栈中查找最贵祸首的线程
第二步已经找到了这个罪魁祸首的线程 PID,并把它转换成了 16 进制的,第三步保存下来的线程栈中有所有线程的 PID 16 进制信息,我们在线程栈中查找这个16进制的线程 id (0x35bc)。

怎么样,现在一目了然了,线程名称、线程状态、以及哪行代码消耗了最多的 CPU 都很清楚了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
Spring MVC 拦截器 interceptor 用法详解
这篇文章主要介绍了Spring MVC 拦截器 interceptor 用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07
SpringBoot统计一个Bean中方法的调用次数的实现步骤
这篇文章主要给大家介绍了SpringBoot统计一个Bean中方法的调用次数的实现步骤,文中通过代码示例和图文结合的方式给大家讲解的非常详细,对大家的学习具有一定的帮助,需要的朋友可以参考下2024-01-01
解决spring-boot2.0.6中webflux无法获得请求IP的问题
这几天在用 spring-boot 2 的 webflux 重构一个工程,写到了一个需要获得客户端请求 IP 的地方,在写的过程中遇到很多问题,下面小编通过一段代码给大家介绍解决spring-boot2.0.6中webflux无法获得请求IP的问题,感兴趣的朋友跟随小编一起看看吧2018-10-10
Springboot详细讲解RocketMQ实现顺序消息的发送与消费流程
RocketMQ作为一款纯java、分布式、队列模型的开源消息中间件,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等,本篇我们了解如何实现顺序消息的发送与消费2022-06-06
IntelliJ IDEA 15款超级牛逼插件推荐(自用,超级牛逼)
这篇文章主要给大家推荐介绍了IntelliJ IDEA 15款超级牛逼插件,这15款插件都是自用的,真的非常推荐,需要的朋友可以参考下2020-11-11
JAVA面试题 简谈你对synchronized关键字的理解
这篇文章主要介绍了JAVA面试题 请谈谈你对Sychronized关键字的理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2019-07-07


最新评论