2011-07-21 64 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

相关问题