linux下java多线程_Linux系统下Java问题排查——cpu使用率过高或多线程锁问题

原标题:Linux系统下Java问题排查——cpu使用率过高或多线程锁问题

一个系统、特别是多线程并发的后台系统,在某些特定场景下,可能触发系统中的bug:导致cpu一直居高不下、进程hang了或处理效率低下,这种问题往往是由于死循环或线程锁导致的,如何找到出现问题的地方,进而修复问题。下面讲讲遇到这种问题时的一般处理方法:

63ffa4ead900f98cea26015662554fcc.gif

1、首先使用top命令找出cpu使用率高的进程,这步主要是为了获取进程PID。

top或者 ps –ef|grep java

如下图cpu 使用率较高的是进程编号是 6685。

4f9da5542165123365d0b56eb2d8dc65.png

358cd235064f50188ae484f220b27971.gif

2、通过top命令定位问题进程中每个线程占用cpu情况。

top -p 6685 -H

进程PID6685的每一个线程占用CPU情况,如下图,正常这些线程cpu使用率是一致变化的,如果有哪个线程cpu使用率一直居高不下,那说明这个线程可能存在问题。

5f3cc1b0a1096404983274093a9fc923.png

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中快速查找文件内容的几个命令。

3cdfc9f8bf0c2179a8360f63a9b7ec9a.png

如下图,这是通过如上方法发现一个线程cpu使用率居高不下,原因是该线程跑到这个循环了,出现死循环。

037fc4e1112ad7a1c5de91b8b158e4c1.png

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();

}

}

}

}

ea9e9b47c325f095eed3c3eefe0856b7.gif

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值