实在是这个月该类问题比较突出了,几乎是每个星期都出现同样的问题,资源在下载到执行机器后,进行操作的线程突然就没了,但是在前端显示这个进程还在运行着,这就导致卡死了,(用户已经等待了几个小时了)。
这问题已经定位到了具体的位置了,就几行代码,
class ProcessUtil{
public void executor(){
String file = "......";
Pressess process = null;
try{
process = Runtime.getRuntime().exec(file);
}
catch(Throwable e){
logger.err();
}finally{
waitfor();
}
}
}
每次都发生在资源部署结束后,(下载资源包,马上开始调用解压,执行等命令的时候)
我这种菜鸟怎么可能独立找到问题所在呢,只有谷歌才能救我了。。。。
原因就是这些:
1. 主进程中调用Runtime.exec会创建一个子进程,用于执行脚本。子进程创建后会和主进程分别独立运行。
2. 因为主进程需要等待脚本执行完成,然后对脚本返回值或输出进行处理,所以这里主进程调用Process.waitfor等待子进程完成。
3. 通过shell脚本可以看出:子进程执行过程就是不断的打印信息。主进程中可以通过Process.getInputStream和Process.getErrorStream获取并处理。
4. 这时候子进程不断向主进程发生数据,而主进程调用Process.waitfor后已挂起。当前子进程和主进程之间的缓冲区塞满后,子进程不能继续写数据,然后也会挂起。
5. 这样子进程等待主进程读取数据,主进程等待子进程结束,两个进程相互等待,最终导致死锁。
嘿嘿————
其实就是一个原因:空间满了。
查了好几个地方的解决方法:基本上都是开线程,单独开启两个额外的线程,分别处理InputStream和ErrorStream就可以了。
代码就不写了,没发现有什么区别,都一样。
最关键的是,因为历史原因,产品的执行环境实在win7环境运行的,然后安装了cygwin64后模拟出的linux环境,所以实际上是window下的java环境。检查环境是一个非常费劲的事。
坑——
参考:
https://blog.csdn.net/seapeak007/article/details/69668600