用Runtime.getRuntime().exec()須要注意的地方

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

相關文章
相關標籤/搜索