是否有一种线程安全的方法可以使用Java 1.6中的ProcessBuilder从外部进程并发使用stdout?
背景:我需要调用pbzip2将大文件解压缩到stdout并在文件解压缩时处理每一行(pbzip2使用多个CPU,与其他实现不同)。
逻辑方法是创建一个子线程来遍历InputStream(即stdout;你不喜欢命名吗?),如下所示:
while((line = reader.readLine()) != null)
{
// do stuff
}
然而,解压缩很慢,所以我真正需要的是reader.readLine方法静静地等待下一行可用,而不是退出。
有没有好办法呢?
答案 0 :(得分:2)
您应该可以使用InputStreamReader和BufferedReader来包装输入流。然后,您可以调用readLine()
,然后根据需要阻止。
请注意,您应该有一个相应的stderr阅读器。您不必对它执行任何操作,但是您需要使用stderr流,否则您生成的进程可能会阻塞。有关链接等,请参阅this answer。
答案 1 :(得分:1)
您自己或多或少都有解决方案。您只需创建一个新线程,该线程从外部进程流中读取循环中的下一行并处理该行。
readLine()将阻塞并等待整个新行可用。如果您使用的是多核/处理器计算机,则在您的线程处理线路时,您的外部进程可以愉快地继续解压缩。 Atleast解压缩可以继续,直到OS管道/缓冲区变满。
请注意,如果您的处理速度低于解压缩,则会阻止解压缩,此时它会成为内存与速度问题。例如你可以创建一个除了读取行之外什么都不做的线程(因此解压缩不会阻塞),将它们缓存在内存中的队列中,另一个线程 - 甚至是几个消耗所述队列的线程。
readLine方法静静等待 下一行可用, 而不是退出
这正是readLine应该做的,它只会阻塞直到整行可用。
答案 2 :(得分:1)
是
我已经编写了一些代码,它们在一个Process(由流程构建器生成)中启动了一个耗时的工作(ffmpeg),然后它启动了我的OutputStreamReader
类,它是一个消耗线程的Thread的扩展。 stdio并用它做了一些魔术。
catch(对我而言)是重定向错误流。这是我的代码片段:
procbbuilder.redirectErrorStream(true);
proc = pb.start();
err = new MyOutputStreamReader(this, proc.getInputStream()); //extenion of thread
err.start();
int exitCode = proc.waitFor();