问题
While running an external script, I want to read the ErrorStream and OutputStream of this script both simultaneously and separately and then process them further. Therefore, I start a Thread
for one of the streams. Unfortunately, the Process
doesn't seem to waitFor
the Thread
to be terminated, but return after the non-threaded stream has no further input.
In a nutshell, here is what I am doing:
ProcessBuilder pb = new ProcessBuilder(script);
final Process p = pb.start();
new Thread(new Runnable() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
...read lines and process them...
}
}).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
...read lines and process them...
int exitValue = p.waitFor();
p.getOutputStream().close();
return exitValue;
Is there any possibility to waitFor
the Thread
to be terminated?
回答1:
You can use Thread.join(...)
to wait for a Thread
to finish. Note that the call throws InterruptedException
if the current thread receives an interrupt before the thread you are waiting for finishes.
回答2:
Here's general code for doing what you want to do. In this case there is both input and output: I am piping someFile
into the process and piping the output to System.out
. Files.copy()
and ByteStreams.copy()
are just Guava convenience methods to hook up an InputStream
to an OutputStream
. We then wait for the command to finish.
final Process pr = Runtime.getRuntime().exec(cmd);
new Thread() {
public void run() {
try (OutputStream stdin = pr.getOutputStream()) {
Files.copy(someFile, stdin);
}
catch (IOException e) { e.printStackTrace(); }
}
}.start();
new Thread() {
public void run() {
try (InputStream stdout = pr.getInputStream()) {
ByteStreams.copy(stdout, System.out);
}
catch (IOException e) { e.printStackTrace(); }
}
}.start();
int exitVal = pr.waitFor();
if( exitVal == 0 )
System.out.println("Command succeeded!");
else
System.out.println("Exited with error code " + exitVal);
A more verbose version if you are running prior to Java 7 with the try-with-resources block:
final Process pr = Runtime.getRuntime().exec(cmd);
new Thread() {
public void run() {
OutputStream stdin = null;
try {
Files.copy(someFile, stdin = pr.getOutputStream());
}
catch (IOException e) { e.printStackTrace(); }
finally {
if( stdin != null ) {
try { stdin.close(); }
catch (IOException e) { e.printStackTrace(); }
}
}
}
}.start();
new Thread() {
public void run() {
InputStream stdout = null;
try {
ByteStreams.copy(stdout = pr.getInputStream(), System.out);
}
catch (IOException e) { e.printStackTrace(); }
finally {
if( stdout != null ) {
try { stdout.close(); }
catch (IOException e) { e.printStackTrace(); }
}
}
}
}.start();
int exitVal = pr.waitFor();
if( exitVal == 0 )
System.out.println("Command succeeded!");
else
System.out.println("Exited with error code " + exitVal);
来源:https://stackoverflow.com/questions/15482492/process-waitfor-a-thread