今日開發的時候使用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(); }