当我们运行程序的时候,如果导致CPU大量被消耗,可能是我们的Java程序出现了问题,就需要定位到可能消耗大量CPU的线程,如何去做呢?
例如运行下面的程序
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BusyThread {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
createBusyThread();
br.readLine();
Object o = new Object();
createLockThread(o);
createDeadLoc();
}
public static void createBusyThread() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true)
;
}
}, "busyThreadName");
t.start();
}
public static void createLockThread(final Object lock) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
},"lockThreadName");
t.start();
}
public static void createDeadLoc() {
Object a = new Object();
Object b = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (a) {
try {
Thread.sleep(3000);
synchronized (b) {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (b) {
try {
Thread.sleep(3000);
synchronized (a) {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t2");
t1.start();
t2.start();
}
}
1. 获取运行程序的进程id
jps -l
或者
ps -ef | grep BusyThread(运行程序类名)
ethan@ubuntu:~$ ps -ef | grep BusyThread
ethan 4688 1928 0 01:28 ? 00:00:14 /opt/sublime_text/sublime_text BusyThread.java
ethan 5728 5648 0 02:09 pts/4 00:00:00 java BusyThread
ethan 5789 5745 0 02:10 pts/6 00:00:00 grep --color=auto BusyThread
得到应用程序进程 id 为 5728
2. 获取对应进程下最消耗CPU 的线程 id
top -Hp 5728
top - 02:14:44 up 2:39, 1 user, load average: 0.00, 0.12, 0.36
Threads: 14 total, 1 running, 13 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.3 us, 0.7 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 6057032 total, 3926028 free, 1285200 used, 845804 buff/cache
KiB Swap: 4191228 total, 4191228 free, 0 used. 4408076 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5840 ethan 20 0 3419616 27176 15840 R 94.7 0.4 0:03.97 java
5737 ethan 20 0 3419616 27176 15840 S 0.3 0.4 0:00.34 java
5728 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5729 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.06 java
5730 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.01 java
5731 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5732 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5733 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5734 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5735 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5736 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5841 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5842 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
5843 ethan 20 0 3419616 27176 15840 S 0.0 0.4 0:00.00 java
得到最消耗CPU的 线程 id 为 5840
3. 计算对应线程 id 的 十六进制
printf "%x\n" 5840
ethan@ubuntu:~$ printf "%x\n" 5840
16d0
4. 分析对应线程的堆栈信息
jstack 5728 | grep 16d0
ethan@ubuntu:~$ jstack 5728 | grep 16d0
"busyThreadName" #8 prio=5 os_prio=0 tid=0x00007fa5f80cb000 nid=0x16d0 runnable [0x00007fa5e346c000]
表明当前最占据CPU 的线程名为: busyThreadName ,当前处于 Runnable 状态
网友评论