这篇文章主要介绍Java中Process与Runtime()的使用示例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
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()流中的内容,这个就看调用的程序的处理了。
代码如下:
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(); } } } } }
以上是“Java中Process与Runtime()的使用示例”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。