有时候咱们可能须要调用系统外部的某个程序,此时就能够用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序。java
此方法返回一个java.lang.Process对象,该对象能够获得以前开启的进程的运行结果,还能够操做进程的输入输出流。windows
Process对象有如下几个方法:编码
一、destroy() 杀死这个子进程spa
二、exitValue() 获得进程运行结束后的返回状态线程
三、waitFor() 获得进程运行结束后的返回状态,若是进程未运行完毕则等待知道执行完毕code
四、getInputStream() 获得进程的标准输出信息流对象
五、getErrorStream() 获得进程的错误输出信息流blog
六、getOutputStream() 获得进程的输入流进程
如今来说讲exitValue(),当线程没有执行完毕时调用此方法会跑出IllegalThreadStateException异常,最直接的解决方法就是用waitFor()方法代替。ip
可是waitFor()方法也有很明显的弊端,由于java程序给进程的输出流分配的缓冲区是很小的,有时候当进程输出信息很大的时候回致使缓冲区被填满,若是不及时处理程序会阻塞。若是程序没有对进程的输出流处理的会就会致使执行exec()的线程永远阻塞,进程也不会执行下去直到输出流被处理或者java程序结束。
解决的方法就是处理缓冲区中的信息,开两个线程分别去处理标准输出流和错误输出流。
程序以下:
public class ExecTest { public static void main(String[] args) throws IOException, InterruptedException { String cmd = "cmd /c dir c:\\windows"; final Process process = Runtime.getRuntime().exec(cmd); printMessage(process.getInputStream()); printMessage(process.getErrorStream()); int value = process.waitFor(); System.out.println(value); } private static void printMessage(final InputStream input) { new Thread(new Runnable() { public void run() { Reader reader = new InputStreamReader(input); BufferedReader bf = new BufferedReader(reader); String line = null; try { while((line=bf.readLine())!=null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }).start(); } }
如上程序,读取进程的输出信息并打印到控制台就不会发生阻塞,程序能正常的结束。
tips:
cmd命令不能须要加上cmd /c才能执行,否则java会去path中找dir.exe
在windows通常字符集编码为GBK,须要在转换成Reader的时候指定为GBK编码.