2

I have a time consuming task compute() that I want to manually abort on the user input "abort".

To this purpose I have a Runnable InputAbort using an infinite loop and a BufferedReader to scan for the user input. The problem arises when the user decides not to abort the long computation. In this case, the thread running InputAbort does not get interrupted properly preventing the JVM to finish (making the thread a daemon does work, but I think there must be a way to properly end the thread).

The problem does not occur when the user aborts the computation entering "abort". It also does not occur when I delete the line s = br.readLine(); in the Runnable and the user waits for the computation to finish.

Starting the thread and the computation:

ComputationObject co = new ComputationObject();

Runnable rInputAbort = new InputAbort(co);
Thread tInputAbort = new Thread(rInputAbort);

tInputAbort.start();
co.compute();
tInputAbort.interrupt();

Runnable:

public class InputAbort implements Runnable {
    private ComputationObject co;

    public RunnableInputAbort(ComputationObject co) {
        this.co = co;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);
            String s = "";

            while ( ! Thread.currentThread().isInterrupted() ) {
                s =  br.readLine();
                if ( s.equals("abort") ) {
                    co.abort();
                    Thread.currentThread().interrupt();
                }
            }

            br.close();
            isr.close();

        }  catch (Exception e) {
            e.printStackTrace();
        }
    }

}
Burkhard
  • 14,596
  • 22
  • 87
  • 108
  • possible duplicate of [How to timeout a thread](http://stackoverflow.com/questions/2275443/how-to-timeout-a-thread) –  Apr 21 '15 at 11:13
  • This question is *not* a simply asking how to timeout a thread; the thread reading the input must also be made to respond to an interrupt signal, even if it is blocked while reading. – Raedwald Apr 21 '15 at 11:27
  • I know this doesn't answer the question, but is it essential that the user stop the process through the command line? In the past I have used the presence of a file as a way for a user to communicate with a process. Not ideal I know but it would be a solution. The user issues "touch stop.stop" to create a file in the expected place, and the process then terminates because it has seen that the file is there. – Rich Apr 21 '15 at 11:30
  • 1
    duplicate of http://stackoverflow.com/questions/29770514/how-to-properly-interrupt-a-java-thread-which-is-reading-user-input ? – Rich Apr 21 '15 at 11:34

2 Answers2

0

You can't interrupt a thread that is reading input. See How to stop a thread waiting in a blocking read operation in Java?.

If you just want to exit the JVM you could just do:

System.exit(0)
Community
  • 1
  • 1
rghome
  • 8,529
  • 8
  • 43
  • 62
0

Checking for ready() on the BufferedReader solved the problem for me:

while ( ! Thread.currentThread().isInterrupted() ) {
    if ( br.ready() ) {
        s =  br.readLine();
        if ( s.equals("abort") ) {
            cb.doAbort();
            Thread.currentThread().interrupt();
        }
    }
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

Further information here (even if my question really had nothing to do with timeouts):

Is it possible to read from a InputStream with a timeout?

Community
  • 1
  • 1
  • Very very bad idea. The thread will spin on the loop waiting for input and chewing up CPU. – rghome Apr 21 '15 at 14:12
  • I don't quite understand the problem. Was that already a flaw in the original implementation or does the problem come from the check for ready()? Would it help to add sleep(1000) somewhere in the loop? –  Apr 21 '15 at 14:25
  • You could add a sleep at the end of the loop which will help. If you don't have a sleep it will continuously loop and your CPU usage will go to 100% on one core. – rghome Apr 21 '15 at 14:28
  • Ok, thanks. Just to clarify: This does not have anything to do with ``br.ready()``, right? –  Apr 21 '15 at 14:31
  • Yes. Say there is no input, br.ready() returns false, you go to the top of the loop; the thread is not interrupted, you continue and check br.ready() again, etc., etc., several zillion times until someone types something or the program finishes. – rghome Apr 21 '15 at 14:34