原标题:Linux系统下Java问题排查——cpu使用率过高或多线程锁问题
一个系统、特别是多线程并发的后台系统,在某些特定场景下,可能触发系统中的bug:导致cpu一直居高不下、进程hang了或处理效率低下,这种问题往往是由于死循环或线程锁导致的,如何找到出现问题的地方,进而修复问题。下面讲讲遇到这种问题时的一般处理方法:
1、首先使用top命令找出cpu使用率高的进程,这步主要是为了获取进程PID。
top或者 ps –ef|grep java
如下图cpu 使用率较高的是进程编号是 6685。
2、通过top命令定位问题进程中每个线程占用cpu情况。
top -p 6685 -H
进程PID6685的每一个线程占用CPU情况,如下图,正常这些线程cpu使用率是一致变化的,如果有哪个线程cpu使用率一直居高不下,那说明这个线程可能存在问题。
3、通过jstack 命令定位问题代码。
找到上一步中cpu使用率一直高居不下的线程,如PID11319,就将这个PID转换成16进制,易知,PID11319转化成16进制为2c37。命令定位问题代码所示。
jstack 6685 | grep 2c37
到这一步,有些系统就可以看出当前线程正在运行的代码(函数),这种情况下就可以直接去查看代码,寻找问题所在。
在tomcat应用中,只能看到当前的线程名(”http-nio-exec-34”),这时候可以通过日志查到当前线程正在运行位置,命令如下:
cat catalina.out | grep “http-nio-exec-34”
附Linux中快速查找文件内容的几个命令。
如下图,这是通过如上方法发现一个线程cpu使用率居高不下,原因是该线程跑到这个循环了,出现死循环。
4、如果是cpu高居不下,通过如上方法,通常就可以找到问题所在;但如果当系统中出现死锁或处理效率低的情况,cpu使用率并不一定会很高,这时候就需要更进一步寻找问题所在。
使用jstack方法获取进程PID6685包含的运行线程的所有状态。将结果输入在dump.txt文件中,查看每个线程的状态:如果出现BLOCKED和WATING状态的线程正常就是出现锁的问题所在。具体使用如下命令:
jstack -l 6685 >> dump.txt
下面介绍Jstack的输出中,Java线程状态的四种状态及可能的原因:
RUNNABLE 线程运行中或I/O等待
BLOCKED 线程在等待monitor锁(synchronized关键字)
TIMED_WAITING 线程在等待唤醒,但设置了时限
WAITING 线程在无限等待唤醒
public class test2019 {
public static void main(String [] args){
runnable(); //(1)线程一直处于RUNNABLE状态
blocked(); //(2)线程一直处于BLOCKED状态
timedWaiting(); //(3)线程处于TIMED_WAITING状态
waiting(); //(4)线程处于WAITING状态状态
}
public static void runnable(){
int i = 0;
while (true) {
i++;
}
}
public static void blocked(){
Integer lock = 0;
new Thread() {
public void run() {
synchronized (lock) {
try {
Thread.sleep(1000 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
try { Thread.sleep(100); } catch (Exception e)
synchronized (lock) {
try {
Thread.sleep(10 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void timedWaiting() {
Integer lock = 0;
synchronized (lock) {
try {
lock.wait(100 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void waiting() {
Integer lock = 0;
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
责任编辑: