Java Process与Runtime()的使用及调用cmd命令阻塞的解决方案

网友投稿 289 2023-01-09

Java Process与Runtime()的使用及调用cmd命令阻塞的解决方案

java Process与Runtime()使用及调用cmd命令阻塞

java调用cmd执行bat文件有时会出现卡死的现象,当时感觉很迷惑,后来查资料,本来一般都是这样来调用程序并获取进程的输出流的,但是我在windows上执行这样的调用的时候却总是在while那里被堵塞了,结果造成ffmpeg程序在执行了一会后不再执行,这里从官方的参考文档中我们可以看到这是由于缓冲区的问题,由于java进程没有清空ffmpeg程序写到缓冲区的内容,结果导致ffmpeg程序一直在等待。

在网上也查找了很多这样的问题,不过说的都是使用单独的线程来进行控制,我也尝试过很多网是所说的方法,可一直没起什么作用。

一直认为是getInputStream的缓冲区没有被清空,不过问题确实是缓冲区的内容没有被清空,但不是getInputStream的,而是getErrorStream的缓冲区,这样问题就得到解决了。

所以我们在遇到java调用外部程序而导致线程阻塞的时候,可以考虑使用两个线程来同时清空process获取的两个输入流,如下这段程序:

public String excuteBatFile(String file, boolean isCloseWindow)

{

String cmdCommand = null;

String res = null;

if(isCloseWindow)

{

cmdCommand = "cmd.exe /c " + file;

}else

{

cmdCommand = "cmd.exe /k " + file;

}

StringBuilder stringBuilder = new StringBuilder();

Process process = null;

try {

process = Runtime.getRuntime().exec(cmdCommand);

final InputStream is1 = process.getInputStream();

new Thread(new Runnable() {

public void run() {

BufferedReader bufferedReader = null;

String line = null;

try {

bufferedReader = new BufferedReader(

new InputStreamReader(is1, "GBK"));

while((line=bufferedReader.readLine()) != null)

{

stringBuilder.append(line+"\n");

}

is1.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}).start(); // 启动单独的线程来清空p.getInputStream()的缓冲区

InputStream is2 = process.getErrorStream();

BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));

StringBuilder buf = new StringBuilder(); // 保存输出结果流

String line2 = null;

while((line2 = br2.readLine()) != null) buf.append(line2); //

log.info("----res:----" + stringBuilder + "&" + buf);

return stringBuilder + "&" + buf;

} catch (Exception e) {

e.printStackTrace();

return e.toString();

}

}

通过这样我们使用一个线程来读取process.getInputStream()的输出流,使用另外一个线程来获取process.getErrorStream()的输出流,这样我们就可以保证缓冲区得到及时的清空而不担心线程被阻塞了。

当然根据需要你也可以保留process.getInputStream()流中的内容,这个就看调用的程序的处理了。

java Process执行cmd命令流阻塞处理

代码如下:

public static void runCmd() {

Process process = null;

BufferedReader bufferedReader = null;

try {

Logger.getLogger(SystemService.class).info("============= 开始重启机器 =============");

process = Runtime.getRuntime().exec("cmd.exe /c shutdown -r -f -t 0");

bufferedReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(process.getInputStream()), Charset.forName("GB2312")));

// 开启线程读取错误输出,避免阻塞

new StreamInformatonThread(process.getErrorStream(), "error").start();

String outStr;

while ((outStr = bufferedReader.readLine()) != null) {

Logger.getLogger(SystemService.class).info("readLine -------> : " + outStr);

}

Logger.getLogger(SystemService.class).info("============= 重启机器完成 =============");

} catch (IOException e) {

Logger.getLogger(SystemService.class).error("============= 重启机器失败 =============");

e.printStackTrace();

} finally {

if (process != null) {

process.destroy();

}

if (bufferedReader != null) {

try {

bufferedReader.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

import java.io.*;

/**

* @Description:流阻塞处理

* @Author: zhangwenchao

* @Date: 2019/7/9 11:35

*/

public class StreamInformatonThread extends Thread {

private InputStream is;

private String str;

private Logger logger = Logger.getLogger(StreamInformatonThread.class);

public StreamInformatonThread(InputStream is, String str) {

this.is = is;

this.str = str;

}

public void run() {

BufferedReader out = null;

try {

out = new BufferedReader(new InputStreamReader(is, "gbk"));

String line;

while ((line = out.readLine()) != null) {

if (str.equals("error")) {

logger.info("ErrorStream --------> :" +line);

} else {

logger.info("outLine ---------> :" + line);

}

}

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (out != null) {

try {

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:跨越快递物流查询单号怎么查(跨越快递单号查询号码)
下一篇:java 取交集方法retainAll的实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~