Search code examples
javamultithreadingjava.util.scannerblocking

How to check Scanner.hasNext(System.in) with a timeout if nothing is typed?


Scanner sc = new Scanner(System.in);

Scanner can be used for reading text files, user input streams, and more. I am specifically using it for reading user input as is made clear above.

With the Scanner that I made above, because it 'rides' System.in, a call to its hasNext() when there is no next input will cause the relevant thread to block until it has data next and return true when it does. I would like to check, getter style, weather there is data next, not, like hasNext() returns, weather there could be data next.

Other questions have resolved this by starting a thread to wait over hasNext() and that has solved the asker's problem. That wouldn't help my problem.

A useful block of code would be some that calls hasNext() and returns false if it doesn't get an answer within 10ms.

I've read the rules and tried to abide by them, but seen as this is one of my first questions, please sing out if I'm not doing this right.

Thanks in advance.


Solution

  • I see nothing wrong with having a Producer - Consumer here:

    // Shared queue
    final Queue<String> messages = new ConcurrentLinkedQueue<>();
    
    // Non-blocking consumer
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
    ses.scheduleAtFixedRate(new Runnable(){
        @Override
        public void run() {
            // non-blocking
            while((String message = messages.poll()) != null) {
                // do something
            }
        }
    }, 0, 10, TimeUnit.MILLISECONDS);
    
    // Blocking producer
    Scanner sc = new Scanner(System.in);
    while(sc.hasNext()) {
        messages.add(sc.next());
    }
    

    The consumer can then just do non-blocking on the shared Queue. Only the producer knows that it is filled as soon as a new message is read.