有時候咱們可能須要調用系統外部的某個程序,此時就能夠用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編碼.