背景
项目需求中涉及java调用.bat文件进行图像处理,先直接上简略版程序
1 public void draw(){
2
3 //调用bat脚本进行图像处理
4 Process process = null;
5 InputStream in = null;
6 try {
7 process = Runtime.getRuntime().exec("startup.bat");
8
9 //输出测试
10 // in = process.getInputStream();
11 // String line;
12 // BufferedReader br = new BufferedReader(new InputStreamReader(in));
13 // while ((line = br.readLine()) != null) {
14 // System.out.println(line);
15 // }
16
17 //等待
18 process.waitFor();
19
20 } catch (Exception e) {
21
22 } finally {
23 process.destroy();
24 }
25 }
JAVA使用遇到的问题描述
一般需要调用系统命令时,大部分人第一反应肯定是使用Runtime.getRuntime().exec(command)返回一个process对象,再调用process.waitFor()来等待命令执行结束,获取执行结果。
调试的时候发现很奇怪的现象,process.waitFor();一直没有结束,导致线程阻塞再次,强行关闭程序后,发现图像处理只进行了一部分。
于是打算打印process的输出,看是否是图像脚本出现异常。
在启用输出测试的下发代码后,发现process的输出一切正常,process.waitFor()一直再等待,并未结束,此时强行关闭程序后,发现图像处理并之前多操作了一部分
根据现象并查看了JDK的帮助文档,如下
因此,可以得出结论:如果外部程序不断在向标准输出流(对于jvm来说就是输入流)和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitFor()这里。
解决方法:在waitFor()之前,利用单独两个线程,分别处理process的getInputStream()和getErrorSteam(),防止缓冲区被撑满,导致阻塞;
修改后代码
1 public class test {
2
3 public void draw(){
4
5 //调用bat脚本进行图像处理
6 Process process = null;
7 InputStream in = null;
8 try {
9 process = Runtime.getRuntime().exec("startup.bat");
10
11 //输出测试
12 // in = process.getInputStream();
13 // String line;
14 // BufferedReader br = new BufferedReader(new InputStreamReader(in));
15 // while ((line = br.readLine()) != null) {
16 // System.out.println(line);
17 // }
18 //新启两个线程
19 new DealProcessSream(process.getInputStream()).start();
20 new DealProcessSream(process.getErrorStream()).start();
21
22 process.waitFor();
23
24 } catch (Exception e) {
25
26 } finally {
27 process.destroy();
28 }
29 }
30 }
1 public class DealProcessSream extends Thread {
2 private InputStream inputStream;
3
4 public DealProcessSream(InputStream inputStream) {
5 this.inputStream = inputStream;
6 }
7
8 public void run() {
9 InputStreamReader inputStreamReader = null;
10 BufferedReader br = null;
11 try {
12 inputStreamReader = new InputStreamReader(
13 inputStream);
14 br = new BufferedReader(inputStreamReader);
15 // 打印信息
16 // String line = null;
17 // while ((line = br.readLine()) != null) {
18 // System.out.println(line);
19 // }
20 // 不打印信息
21 while (br.readLine() != null);
22 } catch (IOException ioe) {
23 ioe.printStackTrace();
24 }finally {
25 try {
26 br.close();
27 inputStreamReader.close();
28 } catch (IOException e) {
29 e.printStackTrace();
30 }
31 }
32
33 }
34 }
来源:oschina
链接:https://my.oschina.net/u/4287611/blog/3329697