First of all, you should read project homepage thoroughly. The following hints are only the complement to those.
First of all, you need System.in to read from stdin. However, there's no methods in System.in you can use to read one line per time. You can see the type of System.in is an InputStream. Meanwhile, InputStream doesn't support buffering. You may want to use BufferedReader to utilize its readLine() method. But you have to convert an InputStream to an InputStreamReader first, and then to a BufferedReader. So, the code you need is like this,
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
Here, you don't need to define intermediate objects since you only want to use BuffereReader.
The answer is to use StringTokenizer, which has two parameter. The first one is the string you want to parse. The second one is the delimiters, which simply consists of delimiter characters. For this program, they're spaces and tabs. So, you can use " \t" (Note the "space" character before \t). I was also told that the default constructor (only one parameter) uses the " \t\n\r\f" as its default delimiters. So, you can use this smarter way.
Like this, Thread[] threads = new Thread[nums]; where
nums is a variable instead of a constant.
There're two ways. The first one is to use Runnable interface. You define a class which implements the Runnable interface. And then create a thread with an instance of the class you just defined. Like this,
class A implements Runnable {...};
Thread t = new Thread(new A());
The other way to create a thread is to extend Thread. You define a class which extends Thread class. And then create an object of the class you just defined. Like this,
class A extends Thread {...}; Thread t = new A();
Of course, for both methods, you have to override the run() method to do what you need, since the original run() is simply empty. Refer to Creating a Thread in Java for more information
It is partially true that after you create several threads and called their start() method then these threads will run simultaneously. Suppose the thread running main() is called the "main thread". The fact is that after you create and start several threads in the main thread, all these threads will run simultaneously, including the main thread. Then you will find that occassionly the main thread will print out the prompt in between the outputs of the other threads. That's not what you want.
What you want is the other threads run simultaneouly and the main thread
waits there for the finish of all the other threads. After that, the main
thread can continue to print out the prompt and wait for the input from
the user. Here comes the join() method of Thread. Suppose t
is one of the threads created in the main thread and you call
t.join() inside the main thread. Then the main thread will
wait for the finish of thread t and continue to run.
Then you may still find that the outputs of the threads you created
didn't interweave with each other. The reason here is that you call
t.join() right after you start thread t by
calling t.start().
Then you start another thread and call its join() method. This is
the wrong way. The reason is that the main thread can continue to
create the second thread only after the first thread has finished.
So, the correct way is start all threads and then call their join()
method.
You think you should get some error output. That's right. But the error output is directed to the stderr stream rather than the stdout stream. So, if you want your program to get both the stdout stream and stderr stream from the process created, you need to read its stdout stream as well as its stderr stream.
Here comes another problem. Inside the thread, you either have to read the stdout first or the stderr first. Then the stdout and stderr of the process created won't interweave again. If you want them to interweave with each other, you need to create another two threads to read its stdout and stderr concurrently. That's why the homepage of this project mentioned you may need 3 threads to handle one process.
The reason is that some of the commands you can run under the Windows Command or UNIX shell are built-in commands. They're not actually executables on the disk. They're just part of the Windows command or UNIX shell. Under Solaris, you can run "builtin" to get a list of all the built-in commands available.
Note: pwd may not be a built-in command under some platforms, such as Mac.
If one part of the command line you input is exit, then you want your
program to terminate. However, your program is still there. The reason
is that inside your program you create another process by calling
Runtime.exec(). If what exec() runs is exit, it will only
terminate itself, i.e., the process. It doesn't nothing to your program.
Think about how to handle this problem. (hint: System.exit())
Then you need to continue the main thread with printing another prompt, just like what the UNIX shell does.
How can you decide if a line only consists of an enter? The answer
is the readLine() of BufferedReader will return a string with length
0. You can call line.length == 0 to decide this. (suppose
line is the command line you got) You shouldn't call
line == null to decide this, since only when the end of
file is encountered the readLine() will return a null. Normally,
the end of file is indicated by press Ctrl+D in UNIX or Ctrl+Z in
Windows.