2

It seems to me that once a thread starts reading input via System.console().readLine() or System.in.read(), there is absolutely no way in the universe to functionally interrupt the read, except for System.exit() or providing input.

interrupt()ing the reading thread does nothing. Even stop()ing it does nothing. close()ing System.in during System.in.read() does nothing until after the read completes by providing input. The read methods don't take any timeout parameters nor time out on their own.

Is there just no way at all to "unlock" a thread waiting for console input that will never come?

Marnes
  • 651
  • 5
  • 19
  • May be this might help https://stackoverflow.com/questions/9479573/how-to-interrupt-console-readline – Prany May 17 '18 at 15:29
  • Another possibly-relevant question and answers: https://stackoverflow.com/questions/3595926/how-to-interrupt-bufferedreaders-readline?rq=1 – Andrew Henle May 17 '18 at 17:38
  • @Prany that's c#... totally different ecosystem and capabilities – Marnes May 17 '18 at 18:55
  • @AndrewHenle yeah I tried the equivalent of that by closing System.in. It doesn't interrupt the read call. If you close system.in, you still need to enter a character and THEN readLine() throws an exception that releases the call. – Marnes May 17 '18 at 18:57
  • hopeless indeed. It's strange that this issue was not addressed in the Console class. The best I can get is my answer below. – hfmanson Apr 29 '19 at 06:57

1 Answers1

0

I created a variation based on this article


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;

public class ConsoleInputReadTask implements Callable<String> {
    private boolean cont = true;

    public void stop() {
        cont = false;
    }

    public String call() throws IOException {
        BufferedReader br = new BufferedReader(
                new InputStreamReader(System.in));
        System.out.println("ConsoleInputReadTask run() called.");
        String input;
        try {
            // wait until we have data to complete a readLine()
            while (!br.ready()) {
                Thread.sleep(200);
                if (!cont) {
                    System.out.println("ConsoleInputReadTask() stopped");
                    return null;
                }
            }
            input = br.readLine();
        } catch (InterruptedException e) {
            System.out.println("ConsoleInputReadTask() cancelled");
            return null;
        }
        return input;
    }
}

Part of main program

    private ConsoleInputReadTask consoleInputReadTask;

    public String readLine() throws InterruptedException {
        ExecutorService ex = Executors.newSingleThreadExecutor();
        String input = null;
        try {
            Future<String> result = ex.submit(consoleInputReadTask);
            try {
                input = result.get();
            } catch (ExecutionException e) {
                e.getCause().printStackTrace();
            }
        } finally {
            ex.shutdownNow();
        }
        return input;
    }

    public void test() {
        consoleInputReadTask = new ConsoleInputReadTask();
        while ((line = readLine()) != null) {
// ...
        }

You can stop consoleInputReadTask by calling consoleInputReadTask.stop() in another thread

hfmanson
  • 1,446
  • 14
  • 21