我正在尝试使用超时运行外部进程并读取它产生的所有输出。这被证明是一项令人惊讶的艰巨任务。我的基本策略是使用ProcessBuilder启动一个进程并在主线程中读取它的输出。另一个线程是等待超时到期并且(如果需要)调用我传递的ReadableByteChannel上的close(),也传递给它的进程上的调用destroy()。
这似乎可以在打印无限输出的进程上正常工作,甚至可以获得预期的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
}
}
我从未看到第二个打印声明,我的测试永远挂起。 javadoc说close()可以阻止另一个close正在运行,但是我的代码中没有其他的close()调用。还有什么可以导致这个?
答案 0 :(得分:3)
测试永远挂起的原因是ReadableByteChannel.close()将阻止ReadableByteChannel.read()阻止它。
从文档中,阻塞模式下的ReadableByteChannel(默认情况下所有通道都将被阻塞),直到你的ByteBuffer中有一个字节空闲时读取至少一个字节,因此读取将被阻塞。
如果您阅读类java.nio.channels.Channels $ ReadableByteChannelImpl(在Channels.java中找到)的代码,您将看到ReadableByteChannelImpl被评为“不可中断” - 显然,它们意味着它。
如果你调用Process.destroy(),那将终止一个没有产生输入并导致从你的阅读线程中抛出AsynchronousCloseException的进程。