Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Question About Java Threads and Blocking

807589Oct 27 2008 — edited Oct 27 2008
I'm helping someone rehost a tool from the PC to the Sun. We're using the Netbeans IDE and the Java programming language. I took a Java course several years ago, but need some help with something now. We're developing a front-end GUI using Swing to allow users to select different options to perform their tasks. I have a general question that will apply to all cases where we run an external process from the GUI. We have a "CommandProcessor" class that will call an external process using the "ProcessBuilder" class. I'm including the snippet of code below where this happens. We pass in a string which is the command we want to run. We also instantiate a class called "StreamGobbler" my coworker got off the Internet for redirecting I/O to a message window. I'm also including the "StreamGobbler" class below for reference. Here's the "CommandProcessor" class:

// Test ProcessBuilder
public class CommandProcessor {

public static void Run(String[] cmd) throws Exception {
System.out.println("inside CommandProcessor.Run function...");

Process p = new ProcessBuilder(cmd).start();

StreamGobbler s1 = new StreamGobbler("stdin", p.getInputStream());
StreamGobbler s2 = new StreamGobbler("stderr", p.getErrorStream());
s1.start();
s2.start();
//p.waitFor();
System.out.println("Process Returned");
}
}

Here's the "StreamGobbler" class:

import java.lang.*;
import java.io.*;

// Attempt to make the output of the process go to the message window
// as it is produced rather that waiting for the process to finish

public class StreamGobbler implements Runnable {
String name;
InputStream is;
Thread thread;

public StreamGobbler (String name, InputStream is){
this.name = name;
this.is = is;
}

public void start(){
thread = new Thread (this);
thread.start();
}

public void run(){
try{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

while (true){
String s = br.readLine();
if (s == null) break;
System.out.println(s);
//messageWindow.writeToMessageArea("[" + name + "]" + s);
}
is.close();
}
catch(Exception ex){
System.out.println("Problem reading stream" + name + "...:" + ex);
ex.printStackTrace();
}
}
}

The "CommandProcessor" class calls two (2) instances of the "StreamGobbler" class, one for "stdin" and one for "stderr". My coworker discovered these are the 2 I/O descriptors that are needed for the external command we're running in this case. We're actually called the Concurrent Versions System (cvs) command from the GUI. Here's what we need it to do:

We want to display the output real-time as the external process is executing, but we want to block any actions being performed on the GUI itself until the process finishes. In other words, we want to show the user any generated output from the process, but don't want to alllow them to perform any other actions on the GUI until this process has finished. If we use the "waitFor()" function associated with a process, it blocks all external process output until the process has completed and then spews all the output to the screen all at once. That's NOT what we want. Also, if we don't use the "waitFor()" function, the code just continues on as it should, but we don't know how to block any actions on the GUI until this process has finished. My coworker tried the following code, but it also blocked any output until the process had finished:

while (s1.thread.isAlive() || s2.thread.isAlive())
{
// We really don't do anything here
}

I'm pretty sure we have to use threads for the output, but how do we instantly show all output and block any GUI actions?

Thank you in advance for your help!
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Nov 24 2008
Added on Oct 27 2008
4 comments
779 views