views:

123

answers:

3

I am using a thread to capture stream output from a process, and then outputting that stream to the eclipse console. The question I have is when to terminate the thread that is doing the stream output.

Thread t = new Thread(new Runnable(){
  private boolean isProcessDone(Process p)
  {
   //not sure what to do here
  }
  public void run()
  {
   Process p = Runtime.getRuntime().exec("executable with output");
   BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
   BufferedReader error = new BufferedReader (new InputStreamReader(p.getErrorStream()));
   while ( !isProcessDone(p) ) {
    String line;
    if( (line = input.readLine()) != null )
    {
     System.out.println(line);
    }
                if( (line = error.readLine()) != null )
    {
     System.out.println(line);
    }
   }
   input.close(); 
            error.close();   
  }
 });
 t.start();

My question is what belongs in the isProcessDone() function. The example I am basing this off of uses the stream's ready() function, but I am unclear whether this will work for programs that either std::err and std::out, but not both. I also tried using

try{
 p.exitValue();
 return true;
}catch(IllegalThreadStateException e){}
return false;

but then the thread finishes before the while loop has a chance to act on the streams, and the output is lost.

+1  A: 

You will need to have two threads. One to handle the I/O and another to wait for process completion (Process.waitFor()) and set a flag telling the I/O thread to quit when it exhausts the data.

Jim Garrison
+3  A: 

You need to use Process.waitFor() to wait for process completion.

Additionally, you need to consume stdout and stderr concurrently in order to avoid blocking and a possible process hang. Consequently you need two threads to read these streams, and to continue reading whilst the streams are available.

See this Javaworld article for more info and a StreamGobbler implementation to consume the stdout/err.

Brian Agnew
I dont want to hang the main process while I send off this task; that is why I am doing this in a thread. Are you saying I will need multiple threads to handle this task?
Adrian Park
If you try to consume stout then stderr, or stderr then stdout (i.e. not concurrently) then you may encounter blocking behaviour, depending on the quantities of output. So regardless of spawning the process in a new thread, you need to consume the stdout/err in separate threads.
Brian Agnew
Thanks for a good explanation of a (very) confusing Java implementation.
C. Ross
A: 

You need to process reading the output in a separate thread, theres an example here

objects