是否可以使用NIO处理进程中的stdout?我有它使用java.io,但这是一个练习,以了解更多关于NIO和探索性能改进的可能性。
基本上我想尽可能快地将大量文本从stdout流式传输到缓冲区而不会阻塞,然后再处理该缓冲区的内容。麻烦的是,我似乎无法弄清楚正确的伏都教使其与NIO合作。这就是我现在所处的位置:
ProcessBuilder pb = new ProcessBuilder( ... );
Process p = pb.start();
stdout = new StreamConsumer(p.getInputStream());
new Thread(stdout).start();
// other stuff omitted for brevity
StreamConsumer类看起来像这样:
class StreamConsumer implements Runnable
{
private InputStream is;
public StreamConsumer(InputStream is)
{
this.is = is;
}
public void run()
{
try
{
ReadableByteChannel source = Channels.newChannel(is);
// Is it possible get a channel to a ByteBuffer
// or MappedByteBuffer here?
WritableByteChannel destination = ??;
ByteBuffer buffer = ByteBuffer.allocateDirect(128 * 1024);
while (source.read(buffer) != -1)
{
buffer.flip();
while (buffer.hasRemaining())
{
destination.write(buffer);
}
buffer.clear();
}
source.close();
destination.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
答案 0 :(得分:7)
我创建了一个开源库,允许java和子进程之间的非阻塞I / O.该库提供了一个事件驱动的回调模型。这取决于JNA库使用特定于平台的本机API,例如Linux上的epoll,MacOS X上的kqueue / kevent或Windows上的IO完成端口。
该项目名为NuProcess,可在此处找到:
答案 1 :(得分:5)
信不信由你,我认为你想要的可写字节通道是
ByteArrayOutputStream ostream = new ByteArrayOutputStream(<some large number>);
WritableByteChannel destination = Channels.newChannel(ostream);
然后完成
ostream.toByteArray()
包含要处理的字节。或者,如果你想要一个字节缓冲区,
ByteBuffer.wrap(ostream.toByteArray())
我在这里看不到你如何获得runnable以外的输出,但我怀疑你原来的代码有这个。否则,您可能希望StreamConsumer
为Callable<ByteBuffer>
。
答案 2 :(得分:1)
您可能希望StreamConsumer成为Callable。
尝试的另一个非阻塞选项可能是使用Guava的ListenableFuture为您提供成功和失败回调,而无需解释您自己的错误。