今日開發的時候使用jdk自帶的運行時變量 RunTime.getRunTime() 去執行bash命令。
因為該bash操作耗時比較長,所以使用了Process.waitFor()去等待子線程運行結束。
這個時候發現程序卡在waitFor()沒有繼續往下執行。
看了官方解釋:
waitFor:等待子進程執行結束,或者已終止子進程,此方法立即返回。
當RunTime對象調用exec方法后,jvm會創建一個子進程,該子進程與jvm建立三個管道連接:標准輸入流、標准輸出流、標准錯誤流。假設該子進程不斷向標准輸入流、標准輸出流寫數據,而jvm不讀取的話,會導致緩沖區塞滿而無法繼續寫數據,最終堵塞在waitFor這里。
知道了問題所在就好處理了, 我們只需要將子進程返回的信息從緩沖區讀取出來,便可以避免主線程堵塞問題。
public static void main(String[] args){
Process proc = RunTime.getRunTime().exec("sh /home/winnie/dataExtract.sh")
// 標准輸入流(必須寫在 waitFor 之前)
String inStr = consumeInputStream(proc.getInputStream());
// 標准錯誤流(必須寫在 waitFor 之前)
String errStr = consumeInputStream(proc.getErrorStream());
int retCode = proc.waitFor();
if(retCode == 0){
System.out.println("程序正常執行結束");
}
}
/**
* 消費inputstream,並返回
*/
public static String consumeInputStream(InputStream is){
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s ;
StringBuilder sb = new StringBuilder();
while((s=br.readLine())!=null){
System.out.println(s);
sb.append(s);
}
return sb.toString();
}
