码迷,mamicode.com
首页 > 编程语言 > 详细

java调用process线程阻塞问题

时间:2019-12-14 11:55:03      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:pre   修改   nts   eal   adl   处理   reader   描述   根据   

背景

项目需求中涉及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 }

java调用process线程阻塞问题

标签:pre   修改   nts   eal   adl   处理   reader   描述   根据   

原文地址:https://www.cnblogs.com/MacrossFT/p/12038479.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!