I'm trying to implement asynchronous input reading from console in Java.
Basically, I want to do this:
Spawn a thread T which reads on standard input with a readLine() on a BufferedReader
Continue with the program
After 10 seconds, stop T
The problem is the readLine() call in T, which I haven't been able to block.
Since interrupting the thread does not work, I figured I would try and send data to standard input from code, to unblock the readLine().
So I tried the following: after 10 seconds, do
FileOutputStream os = new FileOutputStream(FileDescriptor.in);
os.write("Unblocking line\n");
I thought it would work like this: I'm writing to the standard input as in a pipe, so the code in T should read "Unblocking line\n" and go to the next instruction.
Too bad, this doesn't work: "Unblocking line" is immediately shown on screen as if it was written to standard output, and it doesn't seem to affect the readLine().
So my questions are:
Why is my reasoning wrong?
Is there a simple, clean method to achieve what I want to do? Please note that I'm aware of this solution. Also, please do not suggest using System.setIn: it doesn't work. Finally, I should clarify what I mean by simple and clean: using only threads, and avoiding busy waiting.
Thanks in advance.
EDIT: I don't want to close the standard input, as I want to read again after step #3.
Have you tried to simply call
System.in.close() ?
readLine() has to wait for a user to enter some thing. forever if nothing entered.
In your case, you want the thread to close automatically after 10 seconds if nothing entered I think!
code your thread accordingly. Instead of waiting forever if 10 seconds went without user entering an input then main thread should close input waiting thread.
Related
I have a GUI program written in Java which outputs data to the command line using System.out.println. The data is intended to be piped into another program. As an example, I'll pipe the program through head:
$ java MyProgram | head -n10
I want my program to exit when the pipe is broken: in this case, this should happen after MyProgram has printed out ten lines of text.
There is a similar question on this site, and the solution given there works fairly well; for example, I could have the following running in its own thread:
while(!System.out.checkError()) {
// sleep 100ms
}
System.exit(0);
The problem is that PrintStream.checkError() seems to return true only after you have tried to print to the stream and failed. For that reason, my program does not in fact exit until it has printed out eleven lines of text: the pipe is broken after the first ten, but System.out continues to return true until I try to pipe through the eleventh line.
Printing out extra 'junk' lines in order to trigger an error on the PrintStream is out of the question, since the program on the right hand side of the pipe may be very sensitive to the data it receives.
Calling System.out.flush() inside the loop has no effect on PrintStream.checkError(), even though the source code for PrintStream indicates that it ought to call the private ensureOpen method in that class.
How can I reliably test whether System.out is open without printing anything to it?
'Real world' example: suppose that I have some program consumer that takes in command line input and does something with it. Certain pieces of input will call consumer to fail silently. Since the input to consumer is sometimes long and abstruse, I write a GUI program InputProvider in Java where I can click buttons and have the corresponding commands printed out to stdout. If I pipe the output of InputProvider into consumer, then I am able to control consumer graphically.
Unfortunately, there seems to be no way for InputProvider to notify the user when consumer has shut down, except by attempting to write to consumer and getting an exception of some kind.
I don't think you can fix this in Java. There's nothing wrong with System.out until you write to it and it fails. Another process (head) ended but the Java process can't know about that.
So I think that you have two options.
don't use pipe to head but limit the output in your Java code - then you'll know when to stop
accept that the last line will fail and handle the exception appropriately
Try to set a new stream for the system that way you'll be able to check if that stream is closed or not: OutputStream output = new FileOutputStream("c:\\data\\system.out.txt"); and PrintStream printOut = new PrintStream(output);. Then set it here: System.setOut(printOut); and inside the if you can check if(printOut.checkError())
I don't know if this is a noob question, but in my code:
void process() {
...
while (input.hasNext()) {
\\ DO WHATEVERITNEEDSTODO
}
out.close();
...
}
It does everything in the while statement, but afterwards it doesn't go on and therefore doesn't close. Even when I put System.out.println("Hello hello") instead of out.close() as a simple check, it doesn't print "Hello hello"
I'm basically trying to have out.close() happen after my input has gone through everything. Is there another way to do this?
Per the docs for hasNext(), "This method may block while waiting for input to scan." I'd guess you're running a Scanner on some kind of input that never ends (like maybe System.in?). Therefore, you'd see the body of the loop executing, but eventually, you run out of things to process, and it hangs forever waiting for there to either be a "next" or not.
To put it another way, just because there's nothing presently available to read from the Scanner's underlying stream, it doesn't mean there will never be. As long as the stream remains open, more content may eventually become available to be read.
I want to invoke an external program in java code, then the Google tell me that the Runtime or ProcessBuilder can help me to do this work. I have tried it, and there come out a problem the java program can't exit, that means both the sub process and the father process wait for forever. they are hanging or deadlock.
Someone tell me the reason is that the sub process's cache is too small. when it try to give back data to the father process, but the father process don't read it in time, then both of them hang. So they advice me fork an thread to be in charge of read sub process's cache data. I do it as what they tell me, but there still some problem.
Then I close the output stream which get by the method getOutputStream(). Finally, the program success. But I don't know why it happen? Is there some relationship between the output steam and input stream?
You have provided very few details in your question, so I can only provide a general answer.
All processes have three standard streams: standard input, standard output and standard error. Standard input is used for reading in data, standard output for writing out data, and standard error for writing out error messages. When you start an external program using Runtime.getRuntime().exec() or ProcessBuilder, Java will create a Process object for the external program, and this Process object will have methods to access these streams.
These streams are accessed as follows:
process.getOutputStream(): return the standard input of the external program. This is an OutputStream as it is something your Java code will write to.
process.getInputStream(): return the standard output of the external program. This is an InputStream as it is something your Java code will read from.
process.getErrorStream(): return the standard error of the external program. This is an InputStream as, like standard output, it is something your Java code will read from.
Note that the names of getInputStream() and getOutputStream() can be confusing.
All streams between your Java code and the external program are buffered. This means each stream has a small amount of memory (a buffer) where the writer can write data that is yet to be read by the reader. The writer does not have to wait for the reader to read its data immediately; it can leave its output in the buffer and continue.
There are two ways in which writing to buffers and reading from them can hang:
attempting to write data to a buffer when there is not enough space left for the data,
attempting to read from an empty buffer.
In the first situation, the writer will wait until space is made in the buffer by reading data out of it. In the second, the reader will wait until data is written into the buffer.
You mention that closing the stream returned by getOutputStream() caused your program to complete successfully. This closes the standard input of the external program, telling it that there will be nothing more for it to read. If your program then completes successfully, this suggests that your program was waiting for more input to come when it was hanging.
It is perhaps arguable that if you do run an external program, you should close its standard input if you don't need to use it, as you have done. This tells the external program that there will be no more input, and so removes the possibility of it being stuck waiting for input. However, it doesn't answer the question of why your external program is waiting for input.
Most of the time, when you run external programs using Runtime.getRuntime().exec() or ProcessBuilder, you don't often use the standard input. Typically, you'd pass whatever inputs you'd need to the external program on the command line and then read its output (if it generates any at all).
Does your external program do what you need it to and then get stuck, apparently waiting for input? Do you ever need to send it data to its standard input? If you start a process on Windows using cmd.exe /k ..., the command interpreter will continue even after the program it started has exited. In this case, you should use /c instead of /k.
Finally, I'd like to emphasise that there are two output streams, standard output and standard error. There can be problems if you read from the wrong stream at the wrong time. If you attempt to read from the external program's standard output while its buffer is empty, your Java code will wait for the external program to generate output. However, if your external program is writing a lot of data to its standard error, it could fill the buffer and then find itself waiting for your Java code to make space in the buffer by reading from it. The end result of this is your Java code and the external program are both waiting for each other to do something, i.e. deadlock.
This problem can be eliminated simply by using a ProcessBuilder and ensuring that you call its redirectErrorStream() method with a true value. Calling this method redirects the standard error of the external program into its standard output, so you only have one stream to read from.
hey
As part of a project ive had to write a small IRC client to embed in it. Everything works nicely until the program is closed and the thread that reads input from the IRC channel is waiting for more input and never dies.
while(((inBuffer=in.readLine())!=null)&&(die==false))
inBuffer is simply a string and in is a buffered reader on the socket.
the die variable is a boolean and my thought was that i can set that to true and it will fall out the thread. The problem is that "inBuffer=in.readLine()" is sitting there until it gets another line.
Can someone give me a hand?
Close the in stream, readLine() should then return null instantly.
You could set a timeout on the socket and if you get a timeout exception, you can poll a abort-flag. If it's unset, try again to read.
Shutdown the socket for input. That will deliver a null to the readLine() invocation and terminate the loop.
forgot bufferedReader had a "ready()" method to test if it has anything in the buffer. testing this did the trick.
I have started a process in my Java code, this process take a very long time to run and could generate some output from time to time. I need to react to every output when they are generated, what is the best way to do this?
What kind of reaction are you talking about? Is the process writing to its standard output and/or standard error? If so, I suspect Process.getInputStream and Process.getErrorStream are what you're looking for. Read from both of those and react accordingly. Note that you may want to read from both of them from different threads, to avoid the individual buffer for either stream from filling up.
Alternatively, if you don't need the two separately, just leave redirectErrorStream in ProcessBuilder as false, so the error and output streams are merged.
You should start a thread which reads from the Process.getInputStream() and getErrorStream() (or alternatively use ProcessBuilder.redirectErrorStream(true)) and handle it when something shows up in the stream. There are many ways that how to handle it - the right way depends on how the data is being used. Please tell more details.
Here is one real-life example: SbtRunner uses ProcessRunner to send commands to a command line application and wait for the command to finish execution (the application will print "> " when a command finishes execution). There is some indirection happening to make it easier to read from the process' output (the output is written to a MulticastPipe from where it is then read by an OutputReader).