尼恩说在前面
1.CPU100%,你是怎么处理的? 2.CPU被打满了,你是怎么处理的?
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
本文目录
- 尼恩说在前面
- 1.cpu占用很高的3大类型,9大场景:
- 第1大类型导致CPU100%的问题: 业务类问题
-1.1 死循环
-1.2 死锁
-1.3 不必要的代码块
- 第2大类型导致CPU100%的问题:并发类问题
-1.4 大量计算密集型的任务
-1.5 大量并发线程
-1.6 大量的上下文切换
- 第3大类型导致CPU100%的问题:内存类问题
-1.7 内存不足
-1.8 频繁GC
-1.9 内存泄漏
- 2.CPU100%定位的两大神器:
- 3 CPU 飙升100%的解决思路与方法论
- 4 使用jstack 解决CPU 100%问题实操
- 4.1.jstack命令讲解
- 4.2.使用jstack解决CPU占用很高的问题并定位具体行数
- 5.使用arthas解决CPU占用很高的问题并定位具体行数
- 6.死锁导致CPU占用很高的问题分析
- 7.小提示
- 说在最后:有问题找老架构取经
1.cpu占用很高的3大类型,9大场景:
第1大类型导致CPU100%的问题: 业务类问题
1.1 死循环
while(true)条件
1.2 死锁
1.3 不必要的代码块
synchronized
块,会导致线程竞争和上下文切换第2大类型导致CPU100%的问题:并发类问题
1.4 大量计算密集型的任务
1.5 大量并发线程
1.6 大量的上下文切换
第3大类导致CPU100%的问题:内存类问题
1.7 内存不足
1.8 频繁GC
1.9 内存泄漏
2.CPU100%定位的两大神器:
通常使用的jvm自带的工具jstack, 还有一种就是开源神器arthas,
此面试题的配套视频,请参见《尼恩Java面试宝典核心面试题》第二季。
3 CPU 飙升100%的解决思路与方法论
4 使用jstack 解决CPU 100%问题实操
top 命令查看TOP N线程, jstack命令查看堆栈信息
此面试题的配套视频,请参见《尼恩Java面试宝典核心面试题》第二季。
4.1.jstack命令讲解
常用例子: jstack -l pid,查看线程的堆栈信息
yupengdembp:TestYupeng yupeng$ jstack -l 43953
2024-06-08 10:14:45
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode):
"Attach Listener" #10 daemon prio=9 os_prio=31 tid=0x00007fb54485a000 nid=0x3503 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Service Thread" #9 daemon prio=9 os_prio=31 tid=0x00007fb5430b4000 nid=0x3203 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007fb54407e800 nid=0x3103 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007fb54400f800 nid=0x4203 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007fb54285a000 nid=0x4403 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007fb5430ab000 nid=0x4503 runnable [0x0000700002427000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x000000079570b9e0> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x000000079570b9e0> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:47)
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fb544026000 nid=0x4603 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fb544817000 nid=0x5103 in Object.wait() [0x0000700002098000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000795588ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x0000000795588ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fb54303f800 nid=0x2c03 in Object.wait() [0x0000700001f95000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000795586bf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x0000000795586bf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"main" #1 prio=5 os_prio=31 tid=0x00007fb54280e000 nid=0xe03 waiting on condition [0x0000700001983000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.jvm.JVMtest.main(JVMtest.java:6)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=31 tid=0x00007fb544816800 nid=0x5303 runnable
"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fb544009800 nid=0x2507 runnable
"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fb54300f800 nid=0x2403 runnable
"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fb543010000 nid=0x2303 runnable
"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fb543010800 nid=0x2a03 runnable
"VM Periodic Task Thread" os_prio=31 tid=0x00007fb5430b4800 nid=0x3f03 waiting on condition
JNI global references: 15
"main" #1 prio=5 os_prio=31 tid=0x00007fb54280e000 nid=0xe03 waiting on condition [0x0000700001983000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.jvm.JVMtest.main(JVMtest.java:6)
main
:线程名称#1
:当前线程ID,从main开始,jvm会根据线程创建的顺序为其线程编号prio
:优先级的顺序,一般默认是5os_prio
:线程对应系统的优先级tid
:java内的线程idnid
:操作系统级别的线程id,是一个十六进制NEW
:线程新建,还没开始运行RUNNABLE
:正在java虚拟机中运行的线程BLOCKED
:被阻塞,正在等待监视器锁的线程WAITING
:无限期等待另一个线程执行特定操作的线程TIMED_WAITING
:等待另一个线程执行操作达到指定等待时间的线程TERMINATED
:已经退出的线程nid
4.2.使用jstack解决CPU占用很高的问题并定位具体行数
package com.jvm;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JVMCPU {
private static ExecutorService service = Executors.newFixedThreadPool(5);
private static Object lock = new Object();
public static class yupengTask implements Runnable{
@Override
public void run() {
synchronized (lock){
long sum = 0L;
while(true){
sum +=1;
}
}
}
}
public static void main(String[] args) {
yupengTask yupengTask = new yupengTask();
service.execute(yupengTask);
}
}
nohup java JVMCPU &
运行top
命令可以看到cpu被打满了top -Hp 26964
,如下所示jstack
命令来查看程序的所有堆栈信息,但是,这里需要有一个注意的点,26876这个是一个十进制printf "%x\n"
这个命令jstack -l 26964
打印堆栈信息2024-06-08 12:17:36
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):
"Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00007f006c001000 nid=0xc7f waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"DestroyJavaVM" #9 prio=5 os_prio=0 tid=0x00007f00a0009800 nid=0x6955 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"pool-1-thread-1" #8 prio=5 os_prio=0 tid=0x00007f00a00f0000 nid=0x6960 runnable [0x00007f008b0ef000]
java.lang.Thread.State: RUNNABLE
at JVMCPU$yupengTask.run(JVMCPU.java:14)
- locked <0x00000000f59dfcf0> (a java.lang.Object)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- <0x00000000f59e0ed0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f00a00d4800 nid=0x695e runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f00a00b9800 nid=0x695d waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f00a00b6800 nid=0x695c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f00a00b5000 nid=0x695b runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f00a0082000 nid=0x695a in Object.wait() [0x00007f008b6f5000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000f5988ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000f5988ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f00a007d800 nid=0x6959 in Object.wait() [0x00007f008b7f6000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000f5986c00> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000f5986c00> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007f00a0074000 nid=0x6958 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f00a001e800 nid=0x6956 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f00a0020800 nid=0x6957 runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f00a00d7800 nid=0x695f waiting on condition
JNI global references: 5
JVMCPU.java
的14行左右,这里给出的是14行,但是实际情况是14行的附近"pool-1-thread-1" #8 prio=5 os_prio=0 tid=0x00007f00a00f0000 nid=0x6960 runnable [0x00007f008b0ef000]
java.lang.Thread.State: RUNNABLE
at JVMCPU$yupengTask.run(JVMCPU.java:14)
- locked <0x00000000f59dfcf0> (a java.lang.Object)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
此面试题的配套视频,请参见《尼恩Java面试宝典核心面试题》第二季。
5.使用arthas解决CPU占用很高的问题,定位具体代码行
dashboard 命令查看TOP N线程, thread 命令查看堆栈信息
arthas
dashboard
命令可以看到是哪个线程占用cpu最高thread -n 3
,表示最忙的前3个线程并打印信息JVMCPU.java
的14行程序6.死锁导致CPU占用很高的问题分析
public class DeadlockDemo {
// 创建两个锁对象
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
// 线程1尝试获取lock1,然后获取lock2
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(100); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
});
// 线程2尝试获取lock2,然后获取lock1
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(100); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (lock1) {
System.out.println("Thread 2: Holding lock 2 & 1...");
}
}
});
thread1.start();
thread2.start();
}
}
nohuo java DeadlockDemo &
运行起来这里选择arthas,不选择jstack是因为arthas更加的方便,它的功能也比jstack丰富
thread -b
就可以看到线程具体的情况,在下面的图中已经准确的说明了代码在哪一行此面试题的配套视频,请参见《尼恩Java面试宝典核心面试题》第二季。
7.小提示
说在最后:有问题找老架构取经
大龄男的最佳出路是 架构+ 管理 大龄女的最佳出路是 DPM,
部分历史案例
实现职业转型,极速上岸
关注职业救助站公众号,获取每天职业干货
助您实现职业转型、职业升级、极速上岸
---------------------------------
实现架构转型,再无中年危机
关注技术自由圈公众号,获取每天技术千货
一起成为牛逼的未来超级架构师
几十篇架构笔记、5000页面试宝典、20个技术圣经
请加尼恩个人微信 免费拿走
暗号,请在 公众号后台 发送消息:领电子书
如有收获,请点击底部的"在看"和"赞",谢谢