Java Process.waitFor()、线程和 InputStreams
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2150723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Process.waitFor(), threads, and InputStreams
提问by Kaleb Pederson
In pseudocode, here's what I'm doing:
在伪代码中,这是我在做什么:
Process proc = runtime.exec(command);
processOutputStreamInThread(proc.getInputStream());
processOutputStreamInThread(proc.getErrorStream());
proc.waitFor()
However, sometimes processOutputStreamInThread
doesn't see any output and sometimes it does. Roughly, the method creates a BufferedInputStream
of the command's output and sends it to a logger.
但是,有时processOutputStreamInThread
看不到任何输出,有时却能看到。粗略地说,该方法创建一个BufferedInputStream
命令输出并将其发送到记录器。
Based on what I'm seeing, I'm guessing that command
need not have all it's output dumped into the streams fed by getInputStream()
and getErrorStream()
, thus allowing the stream to be empty.
根据我所看到的,我猜测command
不需要将所有输出转储到由getInputStream()
and馈送的流中getErrorStream()
,从而允许流为空。
The results of my trials are the following questions:
我的试验结果是以下问题:
(1)Does waitFor()
in java.lang.Processrequire the executed program's output to have been read before it returns?
(1)是否waitFor()
在java.lang.Process中需要对已读取的执行程序的输出返回前?
The documentation only states:
该文档仅说明:
causes the current thread to wait, if necessary, until the process represented by this
Process
object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
使当前线程在必要时等待,直到此
Process
对象表示的进程终止。如果子进程已经终止,则此方法立即返回。如果子进程尚未终止,调用线程将被阻塞,直到子进程退出。
(2)Under what conditions do the streams provided by getInputStream
and getErrorStream
need to be closed and/or are they closed automatically?
(2)在什么情况下,流提供getInputStream
和getErrorStream
需要关闭和/或自动关闭?
The documentation only states:
该文档仅说明:
Gets the error stream of the subprocess. The stream obtains data piped from the error output stream of the process represented by this Process object.
Implementation note: It is a good idea for the input stream to be buffered.
获取子进程的错误流。该流从由此 Process 对象表示的进程的错误输出流中获取通过管道传输的数据。
实现说明:缓冲输入流是个好主意。
One user reportsthat he had to close the streams himself, but I get an exception at least part of the time indicating that the stream is already closed when I attempt to do so.
一位用户报告说他必须自己关闭流,但我至少在部分时间收到异常,表明当我尝试这样做时流已经关闭。
Edit:changed getOutputStream
to getInputStream
, now present above.
编辑:更改getOutputStream
为getInputStream
,现在出现在上面。
Resolution:The problem ended up being that in certain cases the threads used to process the output stream wouldn't run until after my very short-lived process had completed, resulting in the input stream giving me no data. waitFor
didn't do any waiting for the output of the executed program. Rather, the program ran and terminated before any output could be gathered.
解决方案:问题最终是在某些情况下,用于处理输出流的线程直到我的非常短暂的进程完成后才会运行,导致输入流没有给我任何数据。 waitFor
没有做任何等待执行程序的输出。相反,程序在可以收集任何输出之前运行并终止。
I used threads because I'm not sure how much output I was going to get on standard error and standard output and I wanted to be able to process both simultaneously, without blocking one or the other should only one of them have data available. But, because my threads can't consistently read the executed program's output, it's a non-solution.
我使用线程是因为我不确定标准错误和标准输出将获得多少输出,并且我希望能够同时处理两者,而不会阻塞一个或另一个,如果只有其中一个有数据可用。但是,因为我的线程不能一致地读取执行程序的输出,所以这是一个非解决方案。
My final coded looked something like this:
我的最终代码如下所示:
ProcessBuilder pb = new ProcessBuilder(cmdargs);
pb.redirectErrorStream(true);
Process proc = pb.start();
processOutputStream(proc.getInputStream());
proc.waitFor()
采纳答案by Alexander Pogrebnyak
If your external process expects something on its stdin
, you MUST close the getOutputStream
. Otherwise you will waitFor
forever.
如果您的外部进程需要一些东西stdin
,您必须关闭getOutputStream
. 否则你将waitFor
永远。
Here is the When Runtime.exec() won't articlefrom JavaWorld which describes different pitfalls of exec method and how to avoid them.
这是JavaWorld的When Runtime.exec() won't 文章,它描述了 exec 方法的不同陷阱以及如何避免它们。
From my experience it's better to consume STDOUT and STDERR of child process ( until they EOF ) and then block in waitFor
. Hopefully at this point you won't have to waitFor long.
根据我的经验,最好使用子进程的 STDOUT 和 STDERR(直到它们 EOF )然后阻止waitFor
. 希望此时您不必等待太久。
An answer to Kaleb's question.
Under normal conditions you shouldn't close the streams, however because you are waitingFor
and for whatever reason it does not have a timeout, you may need to close these streams if you encounter some error conditions in the output and don't want to process child's output further. However, whether the child program will terminate (crash) when it's STDOUT or STDERR pipe is closed at the other end is totally up to that child's implementation. Most shell programs though, will terminate under such conditions.
对 Kaleb 问题的回答。在正常情况下,您不应该关闭流,但是因为您是waitingFor
并且无论出于何种原因它没有超时,如果您在输出中遇到一些错误情况并且不想处理子级的,您可能需要关闭这些流进一步输出。但是,当另一端的 STDOUT 或 STDERR 管道关闭时,子程序是否会终止(崩溃)完全取决于该子程序的实现。但是,大多数 shell 程序将在这种情况下终止。
I really wish waitFor
had some meaningful timeout though and the Process
had a documented way of cleaning up its resources when you've decided to abandon its monitoring.
我真的希望waitFor
有一些有意义的超时,并且Process
当您决定放弃其监视时,有记录的方法来清理其资源。
回答by Kaleb Pederson
I think this is slightly counter-intuitive, but:
我认为这有点违反直觉,但是:
getOutputStream Gets the output stream of the subprocess. Output to the stream is piped into the standard input stream of the process represented by this Process object. Implementation note: It is a good idea for the output stream to be buffered. Returns: the output stream connected to the normal input of the subprocess.
getOutputStream 获取子进程的输出流。流的输出通过管道传输到此 Process 对象表示的进程的标准输入流中。实现说明:缓冲输出流是个好主意。返回: 连接到子进程正常输入的输出流。
I read that as this Output stream from the main process and is attached to the standard input of the sub-process, so when you write to getOutputStream().write() you are actually writing on the stdin.
我从主进程读取了这个输出流,并附加到子进程的标准输入,所以当你写入 getOutputStream().write() 时,你实际上是在标准输入上写入。
Do you possibly want to use .getInputStream()?
你可能想使用 .getInputStream() 吗?
Returns: the input stream connected to the normal output of the subprocess.
返回: 连接到子进程正常输出的输入流。
As for Process.Waitfor() the API docs say:
至于 Process.Waitfor() API 文档说:
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
使当前线程在必要时等待,直到此 Process 对象表示的进程终止。如果子进程已经终止,则此方法立即返回。如果子进程尚未终止,调用线程将被阻塞,直到子进程退出。
I would say the thread this is called in will be blocked until such a time as the process has finished executing - you may still be processing output at this stage depending on the other threads or they may have finished before your thread returns.
我会说这个被调用的线程将被阻塞,直到进程完成执行为止 - 您可能仍在此阶段处理输出,具体取决于其他线程,或者它们可能在您的线程返回之前完成。