Jerry Chen
Jerry Chen

Reputation: 61

Set Time Limit on User Input (Scanner) Java

So I'm trying to read user input using the Scanner class. Is there a simple way to make it so that after 10 seconds it moves onto the next block of code? Thanks

Upvotes: 5

Views: 7408

Answers (2)

jashgopani
jashgopani

Reputation: 573

I found another approach where we can continue our flow after the timeout instead of terminating the program. That can be done via ScheduledExecutorService class. The logic implemented is

  1. Initialize a variable for managing the input state and another one for storing the result. (The input I wanted was boolean)

  2. Schedule the input task at a 0s delay (i.e ask for input immediately)

  3. Schedule another task to check for the input status as per the specified delay

  4. Wait for both the tasks to be completed

  5. Return the result

     import java.util.concurrent.Executors;
     import java.util.concurrent.ScheduledExecutorService;
     import java.util.concurrent.TimeUnit;
     import java.util.concurrent.atomic.AtomicBoolean;
    
     ...
    
     //member variables of class
     private static AtomicBoolean inputValue = new AtomicBoolean(true);
     private static AtomicBoolean inputEntered = new AtomicBoolean(false);
     private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
     ...
    
     public static void main(String[] args) {
    
         try {
             boolean yes = getTimedInput("Enter yes or no", 5);
         } catch (Exception e) {
             e.printStackTrace();
        }
     }
    
     ...
    
     public static boolean getTimedInput(String inputString, long timeoutInSeconds) throws Exception {
    
         System.out.printf("%s [Y/n] [timeout=%ds] >> ", inputString.trim(), timeoutInSeconds);
         scheduler.schedule(() -> {
             try {
                 String s = br.readLine();
                 if (s != null) {
                     inputValue.set(s.trim().equalsIgnoreCase("y"));
                 }
                 inputEntered.set(true);
             } catch (IOException e) {
             }
         }, 0, TimeUnit.SECONDS);
         scheduler.schedule(() -> {
             if (inputEntered.get()) {
             inputEntered.set(false);
             } else {
                 System.out.println("\nInput timed out. Considering it as Y");    
                 inputValue.set(true);
             }
         }, 0, TimeUnit.SECONDS);
         scheduler.awaitTermination(timeoutInSeconds + 1, TimeUnit.SECONDS);
         System.out.println();
         return inputValue.get();
     }
    

Upvotes: 0

fileyfood500
fileyfood500

Reputation: 1321

You can use Timer and TimerTask. TimerTask will allow you to run a task after a certain amount of time, in this case you can use this task to stop waiting for the user.

import java.util.Timer;
import java.util.TimerTask;

...

TimerTask task = new TimerTask()
{
    public void run()
    {
        if( str.equals("") )
        {
            System.out.println( "you input nothing. exit..." );
            System.exit( 0 );
        }
    }    
};

...

Timer timer = new Timer();

timer.schedule( task, 10*1000 );

Scanner sc = new Scanner(System.in);
String in = sc.readLine();

timer.cancel();

So if the user doesn't respond within 10 seconds here, the timer will quit reading input. I stole/adapted this response from this initial post: Time limit for an input

Upvotes: 2

Related Questions