业务背景:
把A系统的附件转换成二进制流传到B系统
原始代码:
private byte[] imgToByte(String path){
URL u;
BufferedInputStream input = null;
ByteArrayOutputStream out = null;
try {
u = new URL(path);
input = new BufferedInputStream(u.openStream());
out = new ByteArrayOutputStream();
byte[] buf = new byte[input.available()];
int numByteRead = 0;
while ((numByteRead=input.read(buf))!=-1){
out.write(buf, 0, numByteRead);
}
byte[] data = out.toByteArray();
return data;
} catch (Exception e) {
throw new Exception(e.getMessage());
}finally{
try {
out.close();
input.close();
} catch (IOException e) {
throw new Exception("关闭流异常:"+e.getMessage());
}
}
问题:
偶尔会出现服务器CPU升高,超过100%,通过分析服务,查出这个方法有一个线程一直在活跃状态,不关闭
此状态是偶发现像,并非每次都是这样
解决方案:
1、既然出现了线程关闭不了,给它来一个多线程的写法,每次只创建一个线程,搞个检测,如果一分钟线程没有关闭,则强制关闭。
线程查的时候说是关闭了,但是while循环并没有结束,CPU还是高
通过日志,发现while循环里numByteRead一直=0,打印了10-20分钟,竟然打印了21G的日志。。。。。
2、通过上次尝试的日志分析,发现如果网络出现问题input.available()=0,byte[] buf的长度就会是0,while循环每次都去读0个字节,导致while死循环,于是,我们如果发现网络有问题,input.available()=0的时候,让线程睡一秒钟,再次尝试去获取,尝试5次还是没有取到,则直接抛异常,修改后的代码如下:
private byte[] imgByteFromImg(String path){
URL u;
BufferedInputStream input = null;
ByteArrayOutputStream out = null;
try {
u = new URL(path);
input = new BufferedInputStream(u.openStream());
out = new ByteArrayOutputStream();
int imgCount = input.available();
int exeNum = 0;
while(imgCount==0 && exeNum<5){
Thread.sleep(1000);
imgCount = input.available();
exeNum = exeNum + 1;
}
log.info("exeNum==============="+exeNum);
if(imgCount==0){
throw new EshopException("获取附件失败");
}else{
byte[] buf = new byte[imgCount];
int numByteRead = 0;
while ((numByteRead=input.read(buf))!=-1){
out.write(buf, 0, numByteRead);
}
byte[] data = out.toByteArray();
return data;
}
} catch (Exception e) {
throw new Exception(e.getMessage());
}finally{
try {
out.close();
input.close();
} catch (IOException e) {
throw new EshopException("关闭流异常:"+e.getMessage());
}
}
}