2011-07-21 96 views
2

我試圖運行一個超時的外部進程並讀取它產生的所有輸出。這被證明是令人驚訝的艱鉅任務。我的基本策略是使用ProcessBuilder啓動一個進程並在主線程中讀取它的輸出。另一個線程是等待超時過期的,並且(如果需要的話)在我已經通過它的ReadableByteChannel上調用close(),同時傳遞給它的Process上的調用destroy()。什麼會導致ReadableByteChannel.close()阻塞?

這似乎在打印無限輸出的過程中工作得很好,即使得到預期的AsynchronousCloseException。然而,對一個程序,只是睡覺無限線程塊上接近測試時:

private void terminateProcess() { 
    try { 
     System.out.println("About to close readChannel."); 
     readChannel.close(); 
     System.out.println("Closed the readChannel."); 
    } catch (IOException e) { 
     // Not relevant 
    } 
} 

我從來沒有看到第二個print語句和我的測試掛起,直到永遠。 javadoc說close()可以阻塞另一個close是否正在運行,但是在我的代碼中沒有其他調用close()。還有什麼可以導致這一點?

回答

3

測試永久掛起的原因是,如果ReadableByteChannel.read()阻塞它,ReadableByteChannel.close()將會阻塞。

從文檔中,處於阻塞模式的ReadableByteChannel(默認情況下所有通道)將會阻塞,直到至少一個字節被讀取,如果ByteBuffer中有空閒字節,則讀取將被阻塞。

如果您閱讀類java.nio.channels.Channels $ ReadableByteChannelImpl(在Channels.java中找到)的代碼,您將看到ReadableByteChannelImpl被評論爲「不是真正可中斷的」 - 顯然,它們表示它。

如果調用Process.destroy(),那將會終止一個沒有產生輸入並導致AsynchronousCloseException從讀線程拋出的Process。

+0

正確無誤,謝謝。關閉後,我正在調用destroy *,因爲你描述的所有原因都失敗了。我有點失望,API沒有完全說實話,但我不能與結果爭論。 –

+0

@Josh Gagnon ReadableByteChannel的API文檔說'其他類型的I/O操作是否可以與讀取操作同時進行取決於通道的類型'。 – EJP

相關問題