title: Stop Scanner from waiting for input
body: <h1>Goal</h1>
  
  <p>I'm currently building (to practice with java) a basic command line multiplayer turn-based game. In this game, each player has 5 seconds to make his move. When he makes his move (or <strong>when the timer ends</strong>) the other player starts his turn, etc etc.
  The server sends a <code>TimerEnded</code> message every time the timer ends.
  My current goal is to achieve flawless input reading that <strong>could be interrupted</strong> when a <code>TimerEnded</code> message arrives to the client.</p>
  
  <h1>Design</h1>
  
  <p>To achieve this I created a singleton called <code>InputManager</code>. This class handles all the input reading stuff. I created a method called <code>ask</code> which takes a callback as parameter. In this method I create a new thread and inside it I wait for an input with <code>Scanner.hasNextInt</code>.
  This class has also the method <code>closeInput</code> which sends an Interrupt message to the thread described above.
  Here's the current implementation of the class:</p>
  
  <pre><code>class InputManager{
      private Thread thread;
      private InputManager(){}
      private static InputManager instance;
      private static InputManager getInstance(){
          if(instance == null){
              instance = new InputManager();
          }
          return instance;
      }
  
      /**
       * Ask user to type a number.
       * @param onSelected When the user has made his choice, this callback will be executed
       */
      public static void ask( Consumer&lt;Integer&gt; onSelected){
          getInstance().thread = new Thread(() -&gt; {
              System.out.println("Type a number:");
  
              Scanner sc = new Scanner(System.in);
              int selection = -1;
              while (selection == -1) {
                  if(Thread.currentThread().isInterrupted()){
                      return;
                  }
                  if(sc.hasNextInt()){
                      selection = sc.nextInt();
                      onSelected.accept(selection);
                  } else {
                      sc.next();
                      selection = -1;
                  }
              }
          });
          getInstance().thread.start();
      }
  
      /**
       * Reset input stream (?)
       */
      public static void closeInput(){
          try {
              getInstance().thread.interrupt();
          } catch(NullPointerException e){
              // do nothing
          }
      }
  }
  </code></pre>
  
  <h1>Problem</h1>
  
  <p>This code is extremely unreliable. I'll show you what I mean in just a moment.
  I made a toy class called Client and in the <code>main</code> I simulated the <code>TimerEnd</code> message income with a timer.</p>
  
  <pre><code>class Client {
      /**
       * Ask user to type a number and send it to the server
       */
      void makeRequest(){
          InputManager.closeInput();
          InputManager.ask((selected) -&gt; {
              System.out.println("Sent message: " + selected);
          });
      }
  
      public static void main(String[] args) {
          Client client = new Client();
  
          client.makeRequest();
  
          // Simulate Server messages
          Timer timer = new Timer();
          timer.scheduleAtFixedRate(new TimerTask() {
              @Override
              public void run() {
                  System.out.println("Message received");
                  client.makeRequest();
              }
          }, 5000, 5000);
      }
  }
  </code></pre>
  
  <p>Here's how it works in action:</p>
  
  <pre><code>Type a number:
  2
  Sent message: 2
  Message received
  Type a number:
  3
  Sent message: 3
  Message received
  Type a number:     // Here I don't type anything
  Message received
  Type a number:
  Message received
  Type a number:
  Message received
  Type a number:     // Here I can send multiple messages on the same "turn"
  1
  Sent message: 1
  2
  Message received
  </code></pre>
  
  <h1>Non-educated guess</h1>
  
  <p>Currently, I guess that Scanner remains waiting for input and so the <code>if(isInterrupted)</code> statement is not hit until an input is given. If so, how can I avoid this behaviour?</p>
  
  <p>I understand that this question is extremely (and maybe unnecessarily) long, and since you read it let me thank you for taking your time.</p>
  
  <h2>Minimal, Complete and Verifiable code</h2>
  
  <pre><code>package com.company;
  
  import java.util.*;
  import java.util.function.Consumer;
  
  
  
  class InputManager{
      private Thread thread;
      private InputManager(){}
      private static InputManager instance;
      private static InputManager getInstance(){
          if(instance == null){
              instance = new InputManager();
          }
          return instance;
      }
  
      /**
       * Ask user to type a number.
       * @param onSelected When the user has made his choice, this callback will be executed
       */
      public static void ask( Consumer&lt;Integer&gt; onSelected){
          getInstance().thread = new Thread(() -&gt; {
              System.out.println("Type a number:");
  
              Scanner sc = new Scanner(System.in);
              int selection = -1;
              while (selection == -1) {
                  if(Thread.currentThread().isInterrupted()){
                      return;
                  }
                  if(sc.hasNextInt()){
                      selection = sc.nextInt();
                      onSelected.accept(selection);
                  } else {
                      sc.next();
                      selection = -1;
                  }
              }
          });
          getInstance().thread.start();
      }
  
      /**
       * Reset input stream (?)
       */
      public static void closeInput(){
          try {
              getInstance().thread.interrupt();
          } catch(NullPointerException e){
              // do nothing
          }
      }
  }
  
  class Client {
      /**
       * Ask user to type a number and send it to the server
       */
      void makeRequest(){
          InputManager.closeInput();
          InputManager.ask((selected) -&gt; {
              System.out.println("Sent message: " + selected);
          });
      }
  
      public static void main(String[] args) {
          Client client = new Client();
  
          client.makeRequest();
          Timer timer = new Timer();
          timer.scheduleAtFixedRate(new TimerTask() {
              @Override
              public void run() {
                  System.out.println("Message received: thread interrupted");
                  client.makeRequest();
              }
          }, 5000, 5000);
      }
  }
  </code></pre>