7

我使用ProcessBuilder來運行進程。我通過提交在線程池中處理它們的相應runnable來處理輸入/輸出流(Executors.newCachedThreadPool())。
我得到的結果,但時不時我什麼都沒有。
例如,如果我這樣做:cmd \C dir到進程生成器我得到dir的結果回來,但有時我什麼也沒有得到(儘管結果似乎從處理process.getInputStream的runnable回來)。
我該如何調試?它顯示了intermitently。 使用相同的代碼我沒有任何問題,當我做new Thread(runnable).start()。在我切換到線程池後開始發生。等待進程和讀取流之間的併發問題?

更新:
我想我找到的東西:
我中Runnable如下:

try { 
    while ((line = br.readLine()) != null) { 
      pw.println(line); 
       sb.append(line); 
    } 
    System.out.println("Finished reading "+sb.length()); 
} catch (IOException e) {    
    e.printStackTrace(); 
} 
finally{ 
    pw.flush();  
    try{ 
    isr.close(); 
    }catch(Exception e){} 
} 

在不工作,它打印Finished reading 521的案件。但我試圖通過pw而不是sb得到結果。
pw是PrintWriter的PW = PrintWriter的(OutputStream中);`其中我通過在可運行

更新2:
似乎:status = process.waitFor();返回較早該處理InputStream的結束該可運行之前。這怎麼會發生?我讀過javadoc:
the calling thread will be blocked until the subprocess exits。那麼這是否意味着我可以在之前返回消耗I/O流?

更新3:
似乎是這裏同樣的問題在Ruby
過程結束和消耗輸出之間存在一些競爭條件

+0

如果進程調用另一個進程,第一個進程可能會過早返回 - 正常行爲。 – Sebastian 2013-03-11 10:21:35

+0

這不是關於過早返回。它是關於在輸出流消耗之前返回* – Jim 2013-03-11 10:45:46

回答

1

是的。進程之間的stdio被緩衝(通常是4KB緩衝區)。進程寫入緩衝區並存在。進程B有兩個線程;一個等待A的結束,另一個讀取A的輸出。無法確定首先執行哪個線程。

因此,在讀取所有緩衝輸出之前,process.waitFor();可能(甚至可能在有大量輸出時)返回。

請注意,沖洗在這裏沒有幫助,因爲它只是確保A有寫入的一切。沒有辦法「強制」B以類似的方式讀取數據。

因此,只有當您從輸入流中讀取EOF時,才應該記住退出狀態並將過程視爲「完全終止」。

編輯一個解決辦法是到waitFor()進入流火雞和轉換火雞成Callable然後你可以提交給執行和使用Future API(example)得到的結果(S)。

+0

那麼應該如何修改我的代碼來處理呢?我現在只需執行'waitFor'並將流代碼讀取器中的代碼發送出去 – Jim 2013-03-11 10:37:12

+1

'waitFor',然後在包含流處理程序的線程上使用join()。或者讓流處理程序在'while()'循環之外調用'waitFor()'使它們在同一個地方。 – 2013-03-11 10:47:32

+0

1)流處理程序被提交給執行程序。我怎樣才能「加入」?2)流處理程序如何調用'waitFor'?結果應該被傳遞給線程,等待進程完成 – Jim 2013-03-11 10:50:42