Can Scanner input in Java have a timeout? [duplicate] - java

Is it possible to set timer for user's input? Wait 10 seconds - do next operation and etc.
I mean for example
//wait several seconds{
String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
//wait server seconds}
//next operation and etc.

A slightly easier way to do this than Benjamin Cox's answer would be to do something like
int x = 2; // wait 2 seconds at most
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < x * 1000
&& !in.ready()) {
}
if (in.ready()) {
System.out.println("You entered: " + in.readLine());
} else {
System.out.println("You did not enter data");
}
This will, however consume more resources than his solution.

Not right out of the box, no. Normally the Reader only breaks out of a read() call when another thread closes the underlying stream, or you reach the end of the input.
Since read() is not all that interruptible this becomes a bit of a concurrent programming problem. The thread that knows about the timeout will need to be able to interrupt the thread that's trying to read the input.
Essentially, the reading thread will have to poll the Reader's ready() method, rather than getting locked in read() when there's nothing to read. If you wrap this polling and waiting operation in a java.util.concurrent.Future, then you call the Future's get() method with a timeout.
This article goes into some detail: http://www.javaspecialists.eu/archive/Issue153.html

BufferedReader inputInt = new BufferedReader(new InputStreamReader(System.in));
Robot enterKey = new Robot();
TimerTask task = new TimerTask() {
public void run() {
enterKey.keyPress(KeyEvent.VK_ENTER);
}
};
Timer timer = new Timer();
timer.schedule(task, 30 * 1000);
userInputanswer = inputInt.read();
timer.cancel();

Related

How to loop an input that is timed? [duplicate]

Is it possible to set timer for user's input? Wait 10 seconds - do next operation and etc.
I mean for example
//wait several seconds{
String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
//wait server seconds}
//next operation and etc.
A slightly easier way to do this than Benjamin Cox's answer would be to do something like
int x = 2; // wait 2 seconds at most
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < x * 1000
&& !in.ready()) {
}
if (in.ready()) {
System.out.println("You entered: " + in.readLine());
} else {
System.out.println("You did not enter data");
}
This will, however consume more resources than his solution.
Not right out of the box, no. Normally the Reader only breaks out of a read() call when another thread closes the underlying stream, or you reach the end of the input.
Since read() is not all that interruptible this becomes a bit of a concurrent programming problem. The thread that knows about the timeout will need to be able to interrupt the thread that's trying to read the input.
Essentially, the reading thread will have to poll the Reader's ready() method, rather than getting locked in read() when there's nothing to read. If you wrap this polling and waiting operation in a java.util.concurrent.Future, then you call the Future's get() method with a timeout.
This article goes into some detail: http://www.javaspecialists.eu/archive/Issue153.html
BufferedReader inputInt = new BufferedReader(new InputStreamReader(System.in));
Robot enterKey = new Robot();
TimerTask task = new TimerTask() {
public void run() {
enterKey.keyPress(KeyEvent.VK_ENTER);
}
};
Timer timer = new Timer();
timer.schedule(task, 30 * 1000);
userInputanswer = inputInt.read();
timer.cancel();

Timelimit for valid Java input without System.exit

I have a question how to implement a variation of whats found here:
Set Time Limit on User Input (Scanner) Java
In my case, I would like to ignore the input if the Timelimit is reached while keeping the program alive.
String str = "";
TimerTask task = new TimerTask(){
public void run(){
if(str.equals("")){
System.out.println("No Valid Input detected");
//TimerTask should end here along with the Input
//Other example has System.exit which will also terminate the
//entire program
}else {
// still keep the program alive. The condition itself isn't
//important.
}
}
Timer timer = new Timer();
timer.schedule(task, 10*1000);
Scanner scanner = new Scanner(System.in);
do{
System.out.println("Type a message");
str = scanner.nextLine();
}while(!str.equals("hello"));
timer.cancel();
REACHED HERE!
If the input is given within 10 seconds(and it's valid), the loop ends and the task is canceled, which is perfect. However, if the input is not valid and the timer ends, I would like for it to stop asking for input and skip to the "REACHED HERE" position. Is that even possible?
As #Sedrick mentions, the simplest solution to this is a second thread. The problem is that reading from System.in is blocking. Clearly the example you linked to solves that problem with a System.exit(), but that's too extreme for your case.
Another spin on it might be to use a Deque (double-ended queue) to relay the input, with the timeout on there:
BlockingDeque<String> deque = new LinkedBlockingDeque<>();
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
String input;
do {
System.out.println("Type a message");
input = scanner.nextLine();
deque.add(input);
} while (!input.equals("hello"));
}).start();
String str;
do {
str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));
System.out.println("REACHED HERE!");
Expanded answer...
The idea above was to only create the thread once, and re-use the deque as the proxy for System.in. But, in the thread, the read from System.in will always be blocking - there's no clean way to interrupt the thread, short of System.exit().
This can be refined a bit though. Firstly, if the thread is marked as a daemon thread, this allows the JVM to shutdown around it still. E.g. if the main() method completes, the JVM will exit cleanly too:
Thread thread = new Thread(() -> {
...
});
thread.setDaemon(true);
thread.start();
However, by using InputStream.available(), it is possible to poll for waiting input. This then makes it possible to interrupt the thread cleanly:
BlockingDeque<String> deque = new LinkedBlockingDeque<>();
Thread thread = new Thread(() -> {
Scanner scanner = new Scanner(System.in);
String input;
try {
do {
if (System.in.available() > 0) {
input = scanner.nextLine();
deque.add(input);
} else
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.err.println("Thread stopped");
break;
}
} while (true);
} catch (IOException ex) {
ex.printStackTrace();
}
});
thread.start();
System.out.println("Type a message");
String str;
do {
str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));
System.out.println("REACHED HERE!");
thread.interrupt();
It looks like there's some risk with the user typing a few letters without a line feed. At the moment that would still hang, but this didn't happen on Windows - apparently data from the command window is only released to System.in line by line.

Interrupt sleep in a single thread

I would like to implement in Java a stop point in the code so that nothing is done in 20 seconds unless the user presses Enter.
For the moment I am just using:
sleep(20000);
I know a thread can be "awaken" by another thread using wait() and notify(), but I would like to know if there is something that does not require throwing a new thread. Ideally, I would like to be able to add a timeout to the read operations on a InputStream from the keyboard, so that I could do something like:
try {
//Here is where the waiting happens
myStream.read();
} catch (TimeoutException e) { }
//... Continue normally
You could instead of sleeping for 20s instead sleep for 1 second intervals and poll to see if the user has entered anything:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (int i = 0; i < 20; i++) {
try {
sleep(1000);
if (in.ready()) {
break;
} else {
System.out.println(i+" seeconds have passed");
}
} catch (InterruptedException | IOException ex) {
}
}
The comments are correct, but to suggest a (somewhat hacky) workaround:
BufferedReader myStream = new BufferedReader(new InputStreamReader(System.in));
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() < (startTime + 20000)) {
if (myStream.ready()) {
//do something when enter is pressed
break;
}
}
A blocking read with timeout interruption cannot be accomplished using one thread since a read from the input stream blocks indefinitely. There is a way to execute a computation with a timeout using a Future, but this involves concurrent programming in the first place.

set timeout for user's input

Is it possible to set timer for user's input? Wait 10 seconds - do next operation and etc.
I mean for example
//wait several seconds{
String s = new BufferedReader(new InputStreamReader(System.in)).readLine();
//wait server seconds}
//next operation and etc.
A slightly easier way to do this than Benjamin Cox's answer would be to do something like
int x = 2; // wait 2 seconds at most
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < x * 1000
&& !in.ready()) {
}
if (in.ready()) {
System.out.println("You entered: " + in.readLine());
} else {
System.out.println("You did not enter data");
}
This will, however consume more resources than his solution.
Not right out of the box, no. Normally the Reader only breaks out of a read() call when another thread closes the underlying stream, or you reach the end of the input.
Since read() is not all that interruptible this becomes a bit of a concurrent programming problem. The thread that knows about the timeout will need to be able to interrupt the thread that's trying to read the input.
Essentially, the reading thread will have to poll the Reader's ready() method, rather than getting locked in read() when there's nothing to read. If you wrap this polling and waiting operation in a java.util.concurrent.Future, then you call the Future's get() method with a timeout.
This article goes into some detail: http://www.javaspecialists.eu/archive/Issue153.html
BufferedReader inputInt = new BufferedReader(new InputStreamReader(System.in));
Robot enterKey = new Robot();
TimerTask task = new TimerTask() {
public void run() {
enterKey.keyPress(KeyEvent.VK_ENTER);
}
};
Timer timer = new Timer();
timer.schedule(task, 30 * 1000);
userInputanswer = inputInt.read();
timer.cancel();

How to automatically close Java server?

I need a way to automatically close the server program which runs by using some sort of timer. Till now this is what I got
long start = System.currentTimeMillis();
long end = start + 10 * 1000; // 60 seconds * 1000 ms/sec
while (System.currentTimeMillis() < end) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(
connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
count = count + 1;
}
welcomeSocket.close();
Is this possible? Please help and don't down vote. I'm kinda a noob regarding client- server in Java.
You can use setSoTimeout for that.
Typically, you'll set that with some value like 100 ms, enter a loop and call accept. When the timeout exception is thrown you'll check to see if its ok to exit or not and either fall out of the loop or keep going.
Then make sure you clean up the socket when you're done.
Run the code you have there in a Thread (named server in the code below), and then start another Thread like this to do an interrupt when you want to exit:
Thread server = {the one you have};
Thread timeout = new Thread() {
public void run() {
long end = start + 10 * 1000;
try {
Thread.sleep(end);
} catch (InterruptedException e) {
//handle this
}
server.interrupt();
}
}
timeout.start();
The socket.accept will now throw InterruptedException and bypass all your other code.
I am not sure if you are okay with Threads. Would still recommend you to have a look at the Timer class.
You can create a Timer, which created a thread to close down your server. You can make your connection as a final variable and then use synchronised access to it to close it once Timer thread kicks in.

Categories