2009-11-03 100 views
2

我正在使用線程捕獲進程的流輸出,然後將該流輸出到eclipse控制檯。我的問題是何時終止正在執行流輸出的線程。使用線程捕獲進程輸出

Thread t = new Thread(new Runnable(){ 
     private boolean isProcessDone(Process p) 
     { 
      //not sure what to do here 
     } 
     public void run() 
     { 
      Process p = Runtime.getRuntime().exec("executable with output"); 
      BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); 
      BufferedReader error = new BufferedReader (new InputStreamReader(p.getErrorStream())); 
      while (!isProcessDone(p)) { 
       String line; 
       if((line = input.readLine()) != null) 
       { 
        System.out.println(line); 
       } 
       if((line = error.readLine()) != null) 
       { 
        System.out.println(line); 
       } 
      } 
      input.close(); 
      error.close();  
     } 
    }); 
    t.start(); 

我的問題屬於isProcessDone()函數。我基於此的示例使用流的ready()函數,但我不清楚這是否適用於std :: err和std :: out程序,但不能同時適用。我使用

try{ 
    p.exitValue(); 
    return true; 
}catch(IllegalThreadStateException e){} 
return false; 

也試過,但隨後線程完成while循環有機會作用於流之前,輸出丟失。

回答

6

您需要使用Process.waitFor()來等待過程完成。

此外,爲了避免阻塞和可能的進程掛起,您需要同時使用stdout和stderr 。因此,您需要兩個線程來讀取這些流,並在流可用時繼續讀取。

請參閱this Javaworld article以獲取更多信息,使用StreamGobbler實現消耗stdout/err。

+0

我不想掛在主流程,而我發送這個任務;這就是爲什麼我在一個線程中這樣做。你是說我需要多個線程來處理這個任務嗎? – 2009-11-03 23:32:16

+0

如果您嘗試消耗stoutr或stderr stout(即不是併發),那麼您可能會遇到阻塞行爲,具體取決於輸出的數量。因此,無論在新線程中產生進程,都需要在單獨的線程中使用stdout/err。 – 2009-11-03 23:34:03

+0

感謝您對(非常)令人困惑的Java實現的很好的解釋。 – 2009-11-09 21:49:41

1

您將需要有兩個線程。一個用於處理I/O,另一個用於等待進程完成(Process.waitFor())並設置一個標誌,告訴I/O線程在耗盡數據時退出。

0

您需要處理讀取一個單獨的線程輸出,那裏有一個例子here

2

您可以使用VerboseProcessjcabi-log(我是一個開發者):

String name = new VerboseProcess(
    new ProcessBuilder("executable with output") 
).stdout(); 

您唯一需要的依賴:

<dependency> 
    <groupId>com.jcabi</groupId> 
    <artifactId>jcabi-log</artifactId> 
    <version>0.7.5</version> 
</dependency>