线上CPU飙到100%?别慌,这3个工具比top快10倍!

线上CPU飙到100%?别慌,这3个工具比top快10倍!

正准备下班,手机突然疯狂震动------生产环境CPU告警!你SSH登上服务器,习惯性地敲下top命令,然后按H切换到线程视图,找到最高CPU的线程,记下PID,转成16进制,再jstack...等你一套操作敲完,5秒过去了,CPU使用率已经降下来了。线索,就这样在指尖溜走。

🔥 传统方法的最大问题

说起定位Java应用CPU使用率高的问题,大部分人的第一反应是:top + jstack

完整流程是这样的:

bash 复制代码
# 第一步:找到Java进程
top

# 第二步:切换到线程视图
按 H 键

# 第三步:记下最高CPU的线程ID(比如12345)

# 第四步:转16进制
printf "%x\n" 12345
# 输出:3039

# 第五步:dump线程栈
jstack <pid> > thread.txt

# 第六步:在文件中搜索 nid=0x3039
grep -A 20 "nid=0x3039" thread.txt

看起来很专业?但有三个致命问题:

1. 命令长,记不住

老实说,你能背下printf "%x\n"这个16进制转换命令吗?反正我每次都要Google一下。遇到线上问题紧张得不行,大脑容易空白,这种命令根本记不住。

2. 流程长,容易出错

6个步骤,任何一步出错都要重来。线程ID记错了?16进制转换算错了?grep的时候少打个0?每一步都是坑。

3. 时机错过,白忙一场

这是最要命的。

CPU飙高往往是瞬时的------可能是某个定时任务触发,可能是流量突增,也可能是GC导致。等你把上面这6步命令敲完,5秒过去了,CPU使用率已经降下来,线程栈里根本看不出问题所在。

就像拿着相机想拍流星,结果还在调焦距,流星已经没了。

我去年就遇到过一次:电商大促期间,订单服务CPU间歇性飙到90%,每次持续2-3秒。等我SSH登上去,top刚打开,CPU就降下来了。来来回回折腾了半小时,一无所获,最后只能扩容服务器硬抗。

那次之后,我决定找更快的工具。

🚀 工具1:show-busy-java-threads.sh - 一键救场

为什么推荐它?

show-busy-java-threads.sh是一个Shell脚本,把上面那6步操作自动化了。一行命令,秒级出结果。

完整的脚本链接,关注公众号回复 thread 可下载。

真实案例:秒级定位死循环

去年有一次,推荐服务的CPU突然飙到300%(4核机器),持续了10多分钟。用户反馈首页加载特别慢。

我第一时间想到了这个脚本:

bash 复制代码
# 直接运行,不需要传任何参数
./show-busy-java-threads.sh

瞬间结果就出来了:

scss 复制代码
[1] Busy(57.0%) thread(23645/0x5c5d) stack of java process(23630):
"recommendation-worker-3" #123 daemon prio=5 os_prio=0 tid=0x00007f8a1c0a1000 nid=0x5c5d runnable
    at com.company.recommend.ContentFilter.isValid(ContentFilter.java:156)
    at com.company.recommend.RecommendEngine.filter(RecommendEngine.java:89)
    at com.company.recommend.RecommendEngine.process(RecommendEngine.java:45)
    ...

[2] Busy(55.2%) thread(23648/0x5c60) stack of java process(23630):
"recommendation-worker-6" #126 daemon prio=5 os_prio=0 tid=0x00007f8a1c0a3800 nid=0x5c60 runnable
    at com.company.recommend.ContentFilter.isValid(ContentFilter.java:156)
    ...

一眼就看出来了:

  • 多个工作线程都卡在ContentFilter.isValid这个方法的156行
  • CPU占用分别是57%和55%

打开代码一看,第156行是个正则表达式匹配,而且是在一个没有break的循环里...找到问题了!

从发现问题到定位代码,很快就搞定。

使用方法

1. 运行脚本:

bash 复制代码
# 自动识别Java进程,显示最繁忙的5个线程
./show-busy-java-threads.sh

# 显示最繁忙的10个线程
./show-busy-java-threads.sh -c 10

# 指定Java进程ID
./show-busy-java-threads.sh -p 12345

# 持续监控模式,每3秒刷新一次
./show-busy-java-threads.sh -c 5 -i 3

2. 输出解读:

脚本会输出:

  • 线程ID(十进制和十六进制)
  • CPU占用百分比
  • 完整的线程栈
  • 自动高亮显示业务代码

优势:

  • ✅ 不用记命令,一行搞定
  • ✅ 不用转16进制,自动完成
  • ✅ 不用grep,直接显示
  • ✅ 支持持续监控,不错过瞬时高峰

适用场景: 适合在生产环境快速救场,尤其是CPU飙高持续时间较短的场景。放在服务器上常备,关键时刻能救命。

📊 工具2:fastthread.io - 在线分析专家

为什么推荐它?

如果说show-busy-java-threads.sh是"急救箱",那fastthread.io就是"体检中心"。

它是一个在线的线程栈分析工具,可以把jstack dump出的线程栈文件上传上去,生成一份详细的可视化报告。不仅能看CPU,还能发现死锁、线程泄漏、阻塞等问题。

什么时候用它?

当你已经用jstack dump了线程栈,但是:

  • 线程太多(几千个),肉眼根本看不过来
  • 想分析线程的整体状态分布
  • 怀疑有死锁或者阻塞
  • 想生成报告给其他人看

我一般会这样用:

  1. 先用show-busy-java-threads.sh快速定位
  2. 如果问题不明显,再用jstack dump完整线程栈
  3. 扔到fastthread.io深度分析

使用步骤

1. 生成线程栈文件:

bash 复制代码
# 获取Java进程ID
jps -l

# dump线程栈(带锁信息)
jstack -l <pid> > thread_dump.txt

2. 访问fastthread.io并上传:

打开 fastthread.io/,把`thread_d...

3. 查看分析报告:

报告包含这些内容:

① 线程总览:

yaml 复制代码
Total Threads: 156
Runnable: 8
Waiting: 120
Timed_Waiting: 25
Blocked: 3

② CPU热点线程: 自动识别出占用CPU最高的线程,按百分比排序。

③ 线程分组统计: 按线程名前缀分组,比如:

makefile 复制代码
http-nio-8080-exec: 50 threads
scheduling-: 10 threads

能快速看出哪个线程池的线程最多。

④ 死锁检测: 如果有死锁,会高亮显示并画出依赖关系图。

⑤ 阻塞分析: 统计哪些线程在等待同一把锁,帮你发现锁竞争问题。

实战技巧

技巧1:多次dump对比

CPU飙高时,连续dump 3次线程栈(间隔1秒),分别上传到fastthread.io。如果某个方法在3次dump中都出现,基本可以确定就是它了。

bash 复制代码
jstack <pid> > dump1.txt
sleep 1
jstack <pid> > dump2.txt
sleep 1
jstack <pid> > dump3.txt

技巧2:关注RUNNABLE状态

CPU高的时候,重点看状态是RUNNABLE的线程。WAITINGTIMED_WAITING的线程不占CPU。

优势:

  • ✅ 可视化报告,一目了然
  • ✅ 自动检测死锁、阻塞等问题
  • ✅ 无需安装,浏览器就能用
  • ✅ 支持多次dump对比分析

适用场景: 适合事后分析、深度排查、生成报告给团队共享。对于复杂的线程问题(死锁、线程泄漏),效果特别好。

🔧 工具3:Arthas - 阿里开源的诊断神器

为什么推荐它?

Arthas是阿里开源的Java诊断工具,功能非常强大,堪称"瑞士军刀"。不仅能定位CPU问题,还能:

  • 反编译线上代码
  • 实时修改日志级别
  • 查看方法调用耗时
  • 查看类加载信息
  • ...

我在之前的文章《线程暴增20K+!一次惊心动魄的Jenkins性能排查之旅》里,就是用Arthas的classloader命令找到了问题的根源。

对于CPU问题,Arthas的thread命令特别好用。

使用方法

1. 安装并启动:

bash 复制代码
# 下载arthas-boot.jar
curl -O https://arthas.aliyun.com/arthas-boot.jar

# 启动并attach到Java进程
java -jar arthas-boot.jar

启动后会列出当前所有Java进程,输入序号选择要诊断的进程:

less 复制代码
[INFO] arthas-boot version: 3.7.1
[INFO] Found existing java process, please choose one and input the serial number.
* [1]: 12345 com.company.Application
  [2]: 23456 org.elasticsearch.bootstrap.Elasticsearch
1

2. 查看CPU占用最高的线程:

bash 复制代码
# 显示CPU占用最高的3个线程
thread -n 3

输出示例:

scss 复制代码
"http-nio-8080-exec-123" Id=156 RUNNABLE (in native)
    at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
    at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
    at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
    ...

"background-task-2" Id=89 RUNNABLE
    at com.company.service.DataProcessor.process(DataProcessor.java:234)
    at com.company.service.DataProcessor.run(DataProcessor.java:156)
    at java.lang.Thread.run(Thread.java:748)

CPU占用: 45.3%

3. 持续监控某个线程:

bash 复制代码
# 查看指定线程ID的详细信息
thread 156

# 每3秒刷新一次
thread -i 3000

4. 查看所有线程的状态分布:

bash 复制代码
thread

会输出:

yaml 复制代码
Threads Total: 156, NEW: 0, RUNNABLE: 8, BLOCKED: 3, WAITING: 120, TIMED_WAITING: 25
ID    NAME                          GROUP           PRIORITY  STATE      %CPU    TIME
89    background-task-2             main            5         RUNNABLE   45.3    0:23.567
156   http-nio-8080-exec-123        main            5         RUNNABLE   12.1    0:08.234
...

优势:

  • ✅ 实时交互,无需重启应用
  • ✅ 功能丰富,一个工具顶十个
  • ✅ 不影响性能,可以在生产环境使用
  • ✅ 社区活跃,文档齐全

适用场景: 适合复杂问题的深度诊断,尤其是需要实时交互、方法追踪的场景。是每个Java工程师都应该掌握的神器。

📋 三个工具对比总结

工具 上手难度 速度 功能丰富度 使用场景
show-busy-java-threads.sh ⭐ 极简 ⚡️ 秒级 ⭐⭐ 单一 生产环境快速救场
fastthread.io ⭐⭐ 简单 ⚡️⚡️ 分钟级 ⭐⭐⭐ 中等 事后深度分析、生成报告
Arthas ⭐⭐⭐ 需学习 ⚡️ 实时 ⭐⭐⭐⭐⭐ 最强 复杂问题诊断、实时监控

我的推荐:

组合使用效果最佳:

  1. 问题发生时,先用show-busy-java-threads.sh快速定位
  2. 如果一次看不出问题,dump完整线程栈扔到fastthread.io分析
  3. 需要深度排查时,用Arthasthreadtracewatch等命令追踪方法

💡 最后的建议

1. 别等出问题再学工具

很多人都是这样:线上出问题了,才开始Google"怎么定位CPU高",然后手忙脚乱。

正确做法:

  • 在测试环境提前把这三个工具装好、玩熟
  • 写个死循环程序,模拟CPU飙高,练习定位
  • 把常用命令整理成checklist,贴在工位上

关键时刻,肌肉记忆能救命。

2. 监控告警要先行

工具再好,也只是"事后诸葛亮"。更重要的是提前发现问题

  • 配置CPU使用率告警(建议阈值70%)
  • 配置JVM线程数告警
  • 配置接口响应时间告警

发现得越早,处理越从容。

3. 养成记录习惯

每次排查完问题,记得写个复盘文档:

  • 问题现象
  • 定位过程
  • 根本原因
  • 解决方案

不是为了写而写,是为了下次遇到类似问题,能快速找到解决思路。


📮 我是稳哥,深耕Java和中间件领域多年,专注分享实战经验和技术干货。

💡 关注我,一起探索:

  • 🔧 线上问题排查实战
  • ⚡ 性能优化真实案例
  • 🎯 架构设计最佳实践
  • 🚀 从原理到实战的技术深度剖析

关注公众号【稳哥的随笔】,让我们一起在技术的道路上不断精进! 🚀
如果这篇文章对你有帮助,欢迎点赞、收藏、转发,你的支持是我创作的最大动力!

相关推荐
没有bug.的程序员3 小时前
金融支付分布式架构实战:从理论到生产级实现
java·分布式·微服务·金融·架构·分布式调度系统
00后程序员张3 小时前
Jenkins Pipeline post指令详解
java·开发语言
radient3 小时前
属于Agent的课本 - RAG
人工智能·后端·程序员
程序员阿达3 小时前
开题报告之基于SpringBoot框架的路面故障信息上报系统设计与实现
java·spring boot·后端
用户3421674905523 小时前
鱼皮模拟面试,吊打面试官
后端
哞哞不熬夜3 小时前
JavaEE--SpringIoC
java·开发语言·spring boot·spring·java-ee·maven
滑水滑成滑头3 小时前
**点云处理:发散创新,探索前沿技术**随着科技的飞速发展,点云处理技术在计算机视觉、自动驾驶、虚拟现实等领域的应用愈发广
java·python·科技·计算机视觉·自动驾驶
千里马-horse4 小时前
fastddsgen.jar 简介
java·jar·fast dds·fastddsgen
TT哇4 小时前
【Maven】Maven设置国内源
java·maven