Java死循环执行InputStream.available()导致CPU占满

问题详细

发现Java应用服务器常年cpu占满的状态,执行top命令发现是某个java进程占满cpu资源。如果网络请求并发大的话,可能直接导致宕机

具体原因

通过几行linux命令,定位到看如下代码:
InputStream in = null;
in = socket.getInputStream();
int count = 0;
while (count == 0) {
count = in.available();//死循环代码消耗cpu
}
这段代码是处理请求后的响应,希望读到输入流里面总的字节大小,且有时候因为网络原因无法一次读到结果,所以加上while循环,但如果一直读不到,那就麻烦了,死循环可能一直执行下去,或者会执行到超时时间自己断开。无论哪种情况,只要依然要发送请求,给运维人员的感觉就是cpu一直被占满。
注:如何定位到问题代码见补充

解决办法

为避免死循环,需要在适当的时候,break出循环。请看修改后的代码:
InputStream in = null;
in = socket.getInputStream();
int count = 0;
int trytimes =0;
while (count == 0) {
count = in.available();
trytimes++;
if(trytimes>maxCustomTimes && count ==0) {
break;
}
}
log.info("-- trytimes: “+ trytimes+”, – count"+count);
if(count!=0) {
byte[] bs = new byte[count];
… //读取输入流里面的内容
}
注:maxCustomTimes 写到配置里面,我设置的是2000000次如果还读不到输入流,可能真的
不会有什么返回到客户端了,直接跳出循环,跳出后判断输入流里面是否有内容,有的话就读出
来,没有的话忽略,或者再break之前,写一些公共返回,提示操作人员没有收到服务端响应。

补充

如何从占满cpu的进程中找到耗费cup资源多的线程,继而找到线程详细信息定位到java类及发生死循环的代码行?
[步骤1]确定java进程编号
在linux服务器上执行top
找到占满cpu线程的PID(进程编号)
[步骤2]查看java中进程里面线程的占比
top -p 进程号-H
[步骤3]查看线程信息
jstack 进程号 |grep -A 10 线程号(16进制)
注:步骤2和步骤3中的进程号为步骤1找出的进程号;
16进制的线程号从步骤2查到的线程号(10进制)转换而来。具体如何转参考 链接: 如何定位到问题代码.

拓展:网络流中 InputStream.available() = 0 问题探究

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值