失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java 使用Process调用exe程序 及 Process.waitFor() 死锁问题了解和解决

java 使用Process调用exe程序 及 Process.waitFor() 死锁问题了解和解决

时间:2022-07-04 14:21:29

相关推荐

java 使用Process调用exe程序 及 Process.waitFor() 死锁问题了解和解决

前言

最近在开发android的同时也在开发java ,碰到了需要使用java 程序调用exe的需求,这里我使用的 process 来调用的。该篇文章 读完需要8+分钟,文章类型为 小白入门类型,此处主要记录,方便以后学习补充… 如有不正确的地方还望海涵 及 指出….

文章参考

process参考

waitfor挂起解析

1. 使用process调用exe程序

ProcessBuilder pb = new ProcessBuilder("C:\\Debug\\TestRedis.exe", keyNmae);pb.redirectErrorStream(true);Process process = pb.start();//可能导致进程阻塞,甚至死锁int ret = process.waitFor();System.out.println("return value:"+ret);System.out.println(process.exitValue());byte[] bytes = new byte[process.getInputStream().available()];process.getInputStream().read(bytes);System.out.println(new String(bytes));

// ProcessBuilder api 方法public ProcessBuilder(String... command) {mand = new ArrayList<>(command.length);for (String arg : command)mand.add(arg);}

首先我们先使用 processBuilder 创建出该对象,该对象我这里暂时使用了第一个参数为 exe 文件的地址,第二个参数为传递参数,是我需要传给exe 的字符串。后边主要就是打印 输入流,获取exe 输出信息。其实到这里java 调用exe 就已经完 了,但是后续开发中遇到一种问题,就是程序莫名死锁,没有响应,于是使用debug 跟进代码,发现程序走到 waitfor 代码行的时候程序就出现了挂起的情况,于是google了一番,明白了其中的原因。

2. waitfor 问题描述分析

1.主进程中调用pb.start会创建一个子进程,用于执行shell /exe 脚本。子进程创建后会和主进程分别独立运行。

2. 因为主进程需要等待脚本执行完成,然后对脚本返回值或输出进行处理,所以这里主进程调用Process.waitfor等待子进程完成。

3. 子进程执行过程就是不断的打印信息。主进程中可以通过Process.getInputStream和Process.getErrorStream获取并处理。

4. 这时候子进程不断向主进程发生数据,而主进程调用Process.waitfor后已挂起。当前子进程和主进程之间的缓冲区塞满后,子进程不能继续写数据,然后也会挂起。

5. 这样子进程等待主进程读取数据,主进程等待子进程结束,两个进程相互等待,最终导致死锁。

3. 死锁问题解决

基于上述分析,只要主进程在waitfor之前,能不断处理缓冲区中的数据就可以。因为,我们可以再waitfor之前,单独启两个额外的线程,分别用于处理InputStream和ErrorStream就可以

try {//获取进程的标准输入流final InputStream is1 = process.getInputStream();//获取进城的错误流final InputStream is2 = process.getErrorStream();//启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流new Thread() {public void run() {BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));try {String line1 = null;while ((line1 = br1.readLine()) != null) {if (line1 != null){}}} catch (IOException e) {e.printStackTrace();}finally{try {is1.close();} catch (IOException e) {e.printStackTrace();}}}}.start();new Thread() {public void run() {BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));try {String line2 = null ;while ((line2 = br2.readLine()) != null ) {if (line2 != null){}}} catch (IOException e) {e.printStackTrace();}finally{try {is2.close();} catch (IOException e) {e.printStackTrace();}}}}.start();//可能导致进程阻塞,甚至死锁int ret = process.waitFor();System.out.println("return value:"+ret);System.out.println(process.exitValue());logger.info("event:{}", "RunExeForWindows",process.exitValue());byte[] bytes = new byte[process.getInputStream().available()];process.getInputStream().read(bytes);System.out.println(new String(bytes));logger.info("event:{}", "RunExeForWindows",new String(bytes));}catch (Exception ex){ex.printStackTrace();try{process.getErrorStream().close();process.getInputStream().close();process.getOutputStream().close();}catch(Exception ee){}}

如此便可以将 waitfor死锁问题避开,看完这个问题,总结一下,多看官方api注释….其实官方已经提示我们,如下 为 api注释

Causes the current thread to wait, if necessary, until the* process represented by this {@code Process} object has* terminated. This method returns immediately if the subprocess* has already terminated. If the subprocess has not yet* terminated, the calling thread will be blocked until the* subprocess exits.@return the exit value of the subprocess represented by this* {@code Process} object. By convention, the value* {@code 0} indicates normal termination.* @throws InterruptedException if the current thread is* {@linkplain Thread#interrupt() interrupted} by another* thread while it is waiting, then the wait is ended and* an {@link InterruptedException} is thrown.

如果需要,导致当前线程等待,直到此{@code Process}对象表示的进程具有终止 如果子进程,此方法立即返回已经终止。 如果子进程还没有终止后,调用线程将被阻塞,直到子进程退出。

7月3日 11:22:55

-- 上海 大白

如果觉得《java 使用Process调用exe程序 及 Process.waitFor() 死锁问题了解和解决》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。