I have a problem with the console output of one of my threads being dropped (in Java). The situation is as follows: I spawn a thread that listens (using a blocking method) for incoming messages. These messages are then asynchronously written to the console. Meanwhile, I read in the user input on the console via System.console().readLine().
The problem is that the text is never written to the console at all. I mean, as the readLine() method is blocking, I would have expected the console at least to show the output that has been written to the console as soon as something is entered in the main thread.. Or am I missing the point here?
The relevant source is
// ...
// handle receiving messages
(new Thread() {
#Override
public void run() {
while (executing) received(new String(subSocket.recv(0)));
}
}).start();
// ...
String input;
try {
while ((input = System.console().readLine()) != null && !input.equals(".")) {
pubSocket.send(input.getBytes(), 0);
Thread.yield();
}
}
catch (Exception ex) { }
finally {executing = false;}
And the received method is
public void received(String s) {
System.console().format("(%s)", s);
System.console().flush();
}
What am I doing wrong? Or is there a better way to do this? I mean, I tried to use a BufferedReader encapsulating the input stream in order to read it linewise and used System.out.format() along with it.. To the same effect - Nothing :(.
Cheers,
fxx
Try something like,
Implement a thread to read from input and store it in synchronized map/vector/list etc..
Another thread is listening on that collection, which will then process the message.
I think this should help in some way... Main thing is, don't run the loop on system input. Give it a try.
Related
I have the following thread:
Thread t1 = new Thread() {
#Override
public void run() {
while (!progress.equals(duration)) {
try {
Thread.sleep(1000);
progress = progress.plusSeconds(1);
// synchronized (this) { while (paused) { this.wait(); } }
} catch (InterruptedException e) {
interrupt();
}
}
}
};
t1.start();
I'm trying to implement a functionality which allows the user to pause and stop this thread using the console. Basically, this:
Scanner sc = new Scanner(System.in);
int choice;
while (t1.isAlive()) {
System.out.println("Choose an option:\n1. Pause/Resume\n2. Stop");
choice = Integer.parseInt(sc.nextLine());
// if (choice == 1) { ... } else if (choice == 2) { t1.interrupt() }
// synchronized (t1) { t1.notify(); }
}
My problem is that once t1 dies, t1.isAlive() evaluates to false, but the program doesn't exit the while loop because it is stuck waiting for one last input from the user. I want to interrupt sc.nextLine(), but I read it is not possible because the thread is blocked. How could I do this?
I tried the following:
Thread t2;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (t1.isAlive()) {
t2 = new Thread() {
#Override
public void run() {
try {
while (!br.ready())
Thread.sleep(200);
choice = Integer.parseInt(br.readLine());
} catch (InterruptedException e) {
} catch (IOException e) {
}
}
};
t2.start();
}
Supposedly, this should allow me to interrupt t2, but I must be doing something wrong because it keeps printing Chose an option: 1. Pause/Resume 2. Stop, so I cannot check if it works.
The crucial issue is that the API of System.in makes no guarantees. A JVM can fulfill the complete JVM spec even if it has a System.in such that, if it is interrupted, nothing happens and it is in fact completely impossible to interrupt System.in, aside from System.exit.
However, most JVM implementations fortunately don't quite work that way: If you raise the interrupt flag on any given thread, 3 things are going to happen:
Any method that is specced to definitely look at em will be interrupted: These are all methods that are declared to throws InterruptedException. All these methods will, if the thread's interrupt flag is raised, stop waiting immediately, lower the flag, and return by way of throwing InterruptedException. Yes, this means that if you first raise the interrupt flag (someThread.interrupt() raises the flag and doesn't do anything else; it's other methods that look at it that makes the magic work), and then invoke e.g. Thread.sleep, the sleep calls returns immediately (by throwing InterruptedEx) and waits no even a single millisecond.
Methods that pause a thread but which are not specced to definitely deal with it properly are in limboland: It is up to the implementation of the java runtime if anything happens. However, usually something will happen. These methods almost always throw some sort of checked exception (for DB connections, SQLEx, for network, file, and pipe operations, IOException); any code that is currently waiting to send or receive data on one of these things will deal with a raised interrupt flag by lowering the flag, aborting the operation, and returning by way of throwing that checked exception with a message that indicates an interruption occurred.
If code is executing that doesn't respond to the interrupt flag at all, then nothing happens: The flag stays raised and the JVM is not going to do anything else; the point of the interrupt flag is that it just gets raised and then you wait until the thread runs code that looks at it. Hopefully, that will happen very soon, but there are no guarantees.
That means that most likely all you need to do is:
In T1
Have some sort of AtomicBoolean object that will be set to true by t1 once the job is completed.
t1 will also raise the interrupt flag of t2 when the job is completed.
In T2
Protect your readLine() call by putting it in a try/catch block, catching IOException. If there is a loop you may also want to consider checking the interrupt flag yourself, in case it is set in between readLine() invokes; you do this with Thread.interrupted(), which returns true and lowers the flag if the flag is up. Generally, something like while (!Thread.interrupted() && other conditions) { /* main loop here */ }.
In the IOException catch handler, check t1's 'we are done' flag (that AtomicBoolean). If it says 'we are done', then interpret the IOEx as simply being notified that the job is done (so, don't log it anywhere - you were expecting it to happen). If, however, the 'we are done' flag isn't set yet, then that IOException is indicating an actual I/O problem with the input pipe, which can happen of course. You should proceed as normal (which usually means, throw it onwards so that the app crashes with a full log, you can't sanely respond to the input pipe getting I/O issues other than to exit with debug info about what happend). So, just throw that IOException. If you can't, throw new UncheckedIOException(thatIoException); is what you are looking for.
The caveat
Just because it works on your system does not mean it will work anywhere else, unfortunately. As I said, on some VM impls System.in.read() is just not interruptable, period. Nothing you can do, other than extremely drastic steps: Stop being a command line app and show a swing GUI window instead or make it a web app of some sort.
Closing notes
ready() and available() are almost completely useless. They aren't broken, in the sense that they do exactly what their javadoc says these methods do, but if you carefully read that javadoc, you'll realize that what they provide is completely useless. The only real way to know if data is available is to actually attempt to read it, which then leads you into the trap of: Well, on some platforms, that's not interruptable. Yup. Sucks. No reliable solution, in the sense that the API guarantees it'll work on all platforms, is available. 99.5% of all code out there that calls these methods is broken. It is highly unlikely that you'd ever want to call these methods.
It looks like an innocent topic, but actually it's a bit more complicated. When you are reading from the standard input, you usually just end up in a call to the operating system. Which will not return until it has actual input to return with, and has no idea about the interruption mechanism of Java. It's described as a by-product here.
What you can do is providing your own InputStream instead of using System.in directly, and implement its read() method in a way that it goes into System.in.read() only when System.in.available() says so. Until then just repeat the check with some delay, like using Thread.sleep() which is prepared to get interrupted anyway:
public static void main(String[] args) {
Thread main = Thread.currentThread();
// try (Scanner sc = new Scanner(System.in)) {
try (Scanner sc = new Scanner(new InputStream() {
#Override
public int read() throws IOException {
while (System.in.available() == 0)
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw new IOException();
}
return System.in.read();
}
})) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {
}
main.interrupt();
}
}).start();
String line = sc.nextLine();
System.out.println(line);
System.out.println(main.isInterrupted());
} catch (Exception ex) {
System.out.println("Time's up, probably. Actual exception: " + ex);
System.out.println(main.isInterrupted());
}
}
If you comment the try(Scanner...-})) { block and uncomment the single-line variant, you can try how it doesn't work in itself: you will always have to input something, only the result of System.out.println(main.isInterrupted()); will tell you if you did it in 5 seconds or it took more time.
Side note: in your own attempt you were interrupting the timer thread itself, you need a reference to the other thread instead, here in this example that's the Thread main variable.
I'm using scanner to read lines from file and replace some text in each line based on given pattern. This is done inside an API. My program is a multithreaded one. At once, more than one thread can call this particular API.
Following is the line scanner initialization line where the thread crashes:
public static void replaceInFile(Properties replacements, Path targetFile) {
...
Scanner in = new Scanner(targetFile, "UTF-8");
...
}
I'm sure no single file will be accessed by two threads at once. Can anyone hint me in the right direction as to what is happening?
UPDATE:
public Void call() throws Exception {
Iterator it = paths.iterator();
while(it.hasNext()){
try {
String filePath = it.next().toString();
//BuildUtil replacer = new BuildUtil();
BuildUtil.replaceInFile(replacements, Paths.get(filePath));
} catch(Exception e) {
e.printStackTrace();
}
}
This is the call() of the thread. Now I observe that it shows "Frame not available" even before stepping into the BuildUtils's replaceInFile method and sometimes after entering in there..I'm not able to figure out what's wrong.. The main thread is exiting I think but I see nothing strange happening here which should make it exit unexpectedly.
I found it. Actually it was my stupidity. I forgot to wait for the threads to exit and so the main thread exited even before threads could complete. Sorry for bothering!
So now I do :
for (int i = 0; i < threadsUsed; i++) {
pool.take().get();
}
for all the threads and shutdown the executor service in finally block
I want to make a Java program to run another Java program. I wrote some code to run another Java program. Jhon.java is a Java file from which I execute the Add.class file. But there is problem while reading output and provide input to subprocess. I have this code.
import java.io.*;
class Jhon
{
public static void main(String args[])
{
try
{
String command="java Add";
Process proc=Runtime.getRuntime().exec(command);
Thread t1=new A(proc);
t1.start();
Thread t2=new B(proc);
t2.start();
proc.waitFor();
t1.join();
t2.join();
}
catch(Exception e)
{}
}
}
class A extends Thread
{
Process proc;
A(Process proc)
{
this.proc=proc;
}
public void run()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
while(true)
{
String s = br.readLine();
OutputStream out = proc.getOutputStream();
out.write(s.getBytes());
out.close();
}
}
catch(Exception e)
{}
}
}
class B extends Thread
{
Process proc;
B(Process proc)
{
this.proc=proc;
}
public void run()
{
try
{
String line="";
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while((line=br.readLine())!=null)
{
System.out.println(line);
}
}
catch(Exception e)
{}
}
}
This is the Add.java file which is executed by Jhon.java file
import java.io.*;
class Add
{
public static void main(String args[])
{
int a,b,c;
try
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter first number");
a=Integer.parseInt(br.readLine());
System.out.println("Enter second number");
b=Integer.parseInt(br.readLine());
c=a+b;
System.out.println("Addition is "+c);
}
catch(IOException e)
{
System.out.println(e);
}
}
}
When I execute the Add.java file from Jhon.java file it asks to enter the first number. After providing the first number, it asks to enter the second number. After providing the second number, it does not print addition. The terminal hangs . So what am I doing wrong? Please give me a solution.
Your class A reads the first line of input, calls getOutputStream() and os.write() to (begin to) send that line to the subprocess and then calls os.close(). After flushing the data, that closes the pipe that communicates to the standard input of the subprocess. It then loops around to read the next line and tries to getOutputStream and write and close again, but the write does nothing because it is buffered and the close actually fails because the pipe is closed but it suppresses the internal exception, I believe so autoclose is safe. It then waits for further input.
Your class Add in the subprocess successfully reads the first line; when it tries to read the second line its standard input (the pipe from the master) has been closed normally, which is considered "EOF" (End Of File). br.readLine() returns null to indicate EOF, but you pass it to Integer.parseInt which causes a NullPointerException, which isn't caught (it's not a subtype of IOException) so the Java default is to display a stacktrace on standard error and exit. Standard error for a subprocess is piped to the master as a separate stream (not "Input" stream) and your master isn't looking at it, so that information is lost.
Meanwhile (the thread for) your class A is still waiting for input. If you enter whatever the end-of-input signal is on your platform (usually control-D on Unix but can be configured to something else, control-Z on Windows) it will treat that as EOF, readLine will return null and so s.getBytes() will throw a NullPointerException which your catch(IOException){} will silently discard, and it will exit with no indication of the numerous problems that actually occurred.
Moral: in addition to trying to write correct code in the first place, realize that humans don't get everything perfect every time, so don't throw away exceptions unless you know for certain what caused them -- and at your stage of learning you don't know. And try not to throw away other error information either (in this case the error stream from the subprocess).
Fixes:
call getOutputStream only once, and for each input line (in the loop if you keep the loop but see next) do os.write(line) and os.flush() but NOT os.close().
either rearrange this to be synchronous as #MadProgrammer commented, or else arrange so that your input-and-send thread t1 terminates when the subprocess exits, or equivalently when the receive-and-display thread t2 terminates -- which it does when br.readLine()==null indicating EOF because the subprocess exited, which class B does test correctly unlike class A. This is hard to do automatically because A is already sitting in readLine which cannot be interrupted, at least not reliably. One simple possibility is to output a message telling the user to now enter the end-of-input signal, and code A to handle EOF correctly.
or, a real kludge but for completeness, make t1 a daemon thread and don't join it. Then main will return which terminates the main thread once the subprocess has exited and t2 has terminated, and the JVM will exit without waiting for t1. Because this is usually a Bad Idea I won't give you 'teh codez' but a little googling will find how to do this.
I'm currently developing a Java command-line application and I want to make it interactive. I mean, I have 2 threads:
one thread is permanently writing some information to stdout
the second thread only reads from stdin and is waiting for some commands from the user
But the point is, it's really annoying when I'm typing a command while the first thread writes something to stdout, the command is "cut".
For example:
I want to type the command 'set infolevel 2', and while I'm typing that, the first thread outputs "some information 1234".
My console output may look like this:
set inf // user typing command into stdin
some information 1234 // first thread writes out information
olevel 2 // continuing reading command from stdin
It would be very awsome if someone could tell me if there's a library/API something like that. Thanks!
I guess you would be using System.out.println for output to the console and new Scanner(System.in); for reading input.
Essentially System.out is a PrintStream and System.in is a InputStream and are different object (and streams) but they both use same source (I guess IDE console or command prompt in your case) so when 2 or more threads will try to use the same source then you will get the behavior you have mentioned because by default same source/console is used by the host environment or user. Read below from Java source:
System.out
/**
* The "standard" input stream. This stream is already
* open and ready to supply input data. Typically this stream
* corresponds to keyboard input or another input source specified by
* the host environment or user.
*/
System.in
/**
* The "standard" output stream. This stream is already
* open and ready to accept output data. Typically this stream
* corresponds to display output or another output destination
* specified by the host environment or user.
As far as I know, there are really no such API's to help you out what you are looking for but there are couple of work around options:
Please note, IMHO Option 3 or any similar solution which is based on synchronization is something which you may not want because it will limit your output'ing capabilities
Option 1:
Configure a different console device and then access it using System.console(). In this case, you will have different sources for read and write to console and hence you will not get what you are seeing. If you don't explicitly configure anything then by default you will get System.console() as NULL
Option 2:
Instead of writing the output to console, use a file to write the output. This will ensure that your input and output stream are not messing up with each other.
Option 3:
If you have same source for both read and write to console, then synchronize the access. Below is same code but please be mindful that you could still see some overlap for the time when object lock is being acquired and released but once lock is acquired or released on System.out or System.in then you will not see overlap.
public class Test {
static Object object = new Object();
public static void main(String[] args) {
new Thread(){
#Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object) {
Date date = new Date();
System.out.println("I am coming from first thread i.e. " + Thread.currentThread().getId() + " : " + date);
}
}
}
}.start();
new Thread(){
#Override
public void run() {
Scanner scanner = new Scanner(System.in);
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object) {
scanner.next();
}
}
}
}.start();
}
}
It seems you need to synchronize the two threads on some kind of object. Something like : private Object lockObject = new Object(); Thread t1 = new Thread() { public void run() {synchronized( lockObject ){ //your code } } };
You could either use locking as svasa suggested in his answer, or modify your code so that you have one thread that does both input and output, and the other thread does the computational work. Use an ArrayBlockingQueue to send the output of the work thread to the I/O thread.
This is a piece of code in a SCJP practice question:
public class Threads2 implements Runnable {
public void run() {
System.out.println("run.");
throw new RuntimeException("Problem");
}
public static void main(String[] args) {
Thread t = new Thread(new Threads2());
t.start();
System.out.println("End of method.");
}
}
It was partly mentioned here.
However, my question is not the prior question. As I run the program on a few machines multiple times, I occasionally get RuntimeException before "run" in the output. This does not make sense to me, as these lines of codes executed in the same thread, so it should have been the reverse order.
Can anyone explain why that happens?
e.printStacktrace is using System.err.
System.out and System.err are different object. It has Buffered writer to display to client window.
Even it will execute in different order , it will go to different Buffer.
If Err buffer prints first err will come first.Otherwise out will come first.