So, I am working on a quiz taking program that works from the command line and the quizzes have time limits. What I want to do, is to stop the quiz right when the user’s time is up even if they’re in the middle of answering a question. I am using Java’s Scanner to get the user’s input, so I want to essentially tell the Scanner object to terminate even if it’s in the middle of accepting input.
Now, I know that I can retroactively punish a user for going over time after the fact, but I simply want the quiz to terminate once the time limit has been exceeded. Is there any way to do this with multithreading for example?
Advertisement
Answer
A Java Scanner is using blocking operations. It is not possible to stop it. Not even using Thread.interrupt();
You can however read using a BufferedLineReader
and be able to stop the thread. It’s not a neat solution, as it involves pausing for short moments (otherwise it would use 100 % CPU), but it does work.
public static class ConsoleInputReadTask { private final AtomicBoolean stop = new AtomicBoolean(); public void stop() { stop.set(true); } public String requestInput() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("ConsoleInputReadTask run() called."); String input; do { System.out.println("Please type something: "); try { // wait until we have data to complete a readLine() while (!br.ready() && !stop.get()) { Thread.sleep(200); } input = br.readLine(); } catch (InterruptedException e) { System.out.println("ConsoleInputReadTask() cancelled"); return null; } } while ("".equals(input)); System.out.println("Thank You for providing input!"); return input; } } public static void main(String[] args) { final Thread scannerThread = new Thread(new Runnable() { @Override public void run() { try { String string = new ConsoleInputReadTask().requestInput(); System.out.println("Input: " + string); } catch (IOException e) { throw new RuntimeException(e); } } }); scannerThread.start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } scannerThread.interrupt(); } }).start(); }