Reputation: 61
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
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
Initialize a variable for managing the input state and another one for storing the result. (The input I wanted was boolean)
Schedule the input task at a 0s delay (i.e ask for input immediately)
Schedule another task to check for the input status as per the specified delay
Wait for both the tasks to be completed
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
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