How do I stop and skip a command after 3.5 seconds? - java

I want to stop and skip a command while it's waiting for input after 3.5 seconds. I have tried to use System.currentTimeMillis() by subtracting from the start time, however the code I made does not skip the input.
food is an arrayList from the table class.
public void timer() {
startTime = System.currentTimeMillis();
while(false||(System.currentTimeMillis()-startTime)<3500)
{
correct = input(); //What I want to skip after 3.5 seconds
}
record();
}
Here is the input() method:
public boolean input()
{
Scanner console = new Scanner (System.in);
//I want to skip everything after this after 3.5 seconds.
int num = console.nextInt();
num--;
System.out.println("You selected " + table.food.get(num).toString());
table.food.remove(num);
if (num==choice)
{
return true;
}
return false;
}

One of the problems you are facing is that any of the Scanner's next methods can not be interrupted when reading from a console. Therefore you have to read the input in a different way, for example by using a InputStreamReader.
After that you can submit a specific task to a ExecutorService that handels the execution of the "input reading" seperately from the main Thread. You will get a Future on which you can define a timeout.
Note that this operation is still blocking (on both threads).
This solution is somewhat based on this article.
import java.io.*;
import java.util.concurrent.*;
public class Test {
static class ReadInput implements Callable<Integer> {
public Integer call() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
while (br.ready() == false) {
Thread.sleep(250);
}
String input = br.readLine();
return Integer.parseInt(input);
} catch (InterruptedException e) {
return null;
}
}
}
public static void main(String[] args) {
Integer input = null;
ExecutorService ex = Executors.newSingleThreadExecutor();
try {
Future<Integer> future = ex.submit(new ReadInput());
input = future.get(3500, TimeUnit.MILLISECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
// handle exceptions that need to be handeled
} finally {
ex.shutdownNow();
}
System.out.println("done: " + input);
}
}
Note that timeout in the ReadInput should be lower than the timeout in the main Thread.

Related

How to ask user for input to console (BufferedReader) and display countdown? Need to do it in two threads

Once user entered data timer stops and BuferredReader closed.
If 10 seconds passed and no input - BuferredReader closed and user unable to make input. Below code works, but not 100% correct.
Please suggest any solution.
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
NewThread nt = new NewThread(br);
Thread newThread = new Thread(nt);
newThread.start();
System.out.print("Please enter data: ");
System.out.println("");
String value = br.readLine();
System.out.println(value);
nt.shutdown();
}
}
class NewThread implements Runnable {
volatile BufferedReader br;
volatile boolean running ;
public NewThread(BufferedReader br) throws IOException {
this.br = br;
this.running = br.ready();
}
#Override
public void run() {
int count = 10;
try {
while (!running) {
System.out.print("("+count +")"+ '\r');
Thread.sleep(1000);
count--;
if (count <0){
shutdown();
}
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
public void shutdown () throws IOException {
running=true;
br.close();
}
}
So, firsty you calling method:
br.readLine()
BufferedReader implementation of this method uses synchornized block when waiting for user input. Below I put part of code this method:
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
...}
Nextly, when you call method shutdown from NewThread(after time out) on your reader, which call close method on buffer - execution of this metod uses synchronized mechanism too:
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
so it means that close method will be executed after finished readLine method (exactly after execution synchronized block in readLine method), which is finished when you pass parameter to console.
I suppose that is not possible to close this reader after calling readLine method by standard java mechanism when you use System.in.

Java Future: Issue while trying to understand .get() method

import java.io.*;
import java.util.concurrent.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
class _TimeOut_ extends PrintIn_Delays {
public static void main(String[] args)
throws InterruptedException {
TimeWait Timeout = new TimeWait();
String input = Timeout.readLine();
String input2 = Timeout.readLine();
}
}
class Reader implements Callable<String> {
public String call() throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String input;
do {
input = br.readLine();
}while ("".equals(input));
return input;
}
}
class TimeWait extends _TimeOut_ {
public String readLine() throws InterruptedException {
ExecutorService ex = Executors.newSingleThreadExecutor();
String input = null;
try {
try {
Future<String> result = ex.submit(
new Reader());
input = result.get(5, TimeUnit.SECONDS);
} catch (ExecutionException e) {
e.getCause().printStackTrace();
} catch (TimeoutException e){}
} finally {
ex.shutdownNow();
}
System.out.println(" "+input);
return input;
}
}
This will wait for 5 seconds for user input. If user don't enter anything, it displays null.
Now the problem is :
When I run it, it waits for 5 seconds for my input but I don't enter anything and so output is null. Then in the second input, I enter 'hi'. But it still waits for 5 seconds ( which it shouldn't) and after taking the input, it still displays null. Here is the output :
null
hi
null
The problem is that even though you are stopping waiting for the first Future to get a value, it doesn't stop waiting for a value. The BufferedReader.readLine() call simply blocks, waiting for input, or closure of the input stream, irrespective of the timeout.
So, when you do eventually enter a value, the first thread gets it; then there is nothing for the second thread to read.
(But, of course, the second thread hasn't stopped waiting either: this will continue to wait for input, or closure of the input stream).

Strange thread behavior

I'm trying to do this: The question is displayed in the console. If during some time the user does not write the answer, then the next question is asked. If the user enters an answer, the next question is asked immediately. My code:
public class Test {
private boolean stopQuestion;
Thread scannerThread = new Thread();
public static void main(final String[] args) {
final Test test = new Test();
test.scannerThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String string;
do {
string = test.requestInput(new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (final InterruptedException e) {
}
test.scannerThread.interrupt();
}
}));
} while (!test.stopQuestion);
System.out.println("Input: " + string);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
});
test.scannerThread.start();
}
public String requestInput(final Thread timer) throws IOException {
final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
timer.start();
System.out.println("Any question");
System.out.println("Please type your answer: ");
try {
while (!br.ready()) {
Thread.sleep(100);
}
} catch (final InterruptedException e) {
System.out.println("Time is over. Next question: ");
return null;
}
System.out.println("Thank You for providing input!");
return br.readLine();
}
}
If you do not write anything to the console, everything seems to work as expected. Time ends and the next question is asked. But if something is written to the console, the timer starts to malfunction and the next question does not wait for the specified amount of time, sometimes it does not wait at all. I do not understand what's the matter.
I created instance of thread outside the method and pass instance to the method as reference but then throws IllegalThreadStateException.
I see two major problems with your code:
You are continously creating threads that are supposed to read input:
do {
string = test.requestInput(new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (final InterruptedException e) {
e.printStackTrace();
}
test.scannerThread.interrupt();
}
}));
} while (!test.stopQuestion); // <-- this is always true
You are opening as many BufferedReaders on System.in as many timer threads you are launching:
final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Also, you are not closing any of these BufferedReader instances.

Java Scanner input in separate thread

I have a multi-threaded command line app. It is a web service client with a pool of 10 threads that churns away, sending requests, batch-style, to a server.
But it runs for a few days, and sometimes further down the pipeline, the queues start getting backed up. So I want to go to the client, press - or + and have that increase or decrease a Thread.sleep(waitingTime), to take pressure off the server.
I tried running a Scanner in a separate thread, but it didn't seem to work. Has anyone managed to get non-blocking I/O working in Java? I presume it's possible, but I'm giving up for now.
Edit: Added test code as per request
package test;
import java.io.*;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by djb on 2015/06/03.
*/
public class ThreadTest {
public ThreadTest() {
}
static long rand = 10000;
public static void main(String args[])
{
ExecutorService executor = Executors.newFixedThreadPool(5);
File f = new File("C:\\code\\ThreadTest\\text.csv");
try {
Runnable keyPressThread = new ThreadTest.KeyPressThread();
Thread t = new Thread(keyPressThread);
t.start();
BufferedReader br = new BufferedReader(new FileReader(f));
String line;
while ((line = br.readLine()) != null)
{
try {
final String copy = line;
executor.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println(rand);
Thread.sleep(rand);
System.out.println(copy);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (Exception e)
{
e.printStackTrace();
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public static class KeyPressThread implements Runnable {
Scanner inputReader = new Scanner(System.in);
//Method that gets called when the object is instantiated
public KeyPressThread() {
}
public void run() {
String input = inputReader.next();
if (input.equals("["))
{
rand+=100;
System.out.println("Pressed [");
}
if (input.equals("]"))
{
rand-=100;
System.out.println("Pressed ]");
}
}
}
}
Your KeyPressThread is only testing once:
This will make it watch constantly.
public void run()
{
while(true)
{
if (inputReader.hasNext())
{
String input = inputReader.next();
if (input.equals("["))
{
rand+=100;
System.out.println("Pressed [");
}
if (input.equals("]"))
{
rand-=100;
System.out.println("Pressed ]");
}
if (input.equalsIgnoreCase("Q"))
{
break; // stop KeyPressThread
}
}
}
}
System.in is line buffered, by default. This means that no input is actually passed to the program until you press ENTER.

unblocked scanner function java [duplicate]

This question already has answers here:
how to read from standard input non-blocking?
(5 answers)
Closed 8 years ago.
I would like to ask to the user if he could press a key before continuing. Then my program will wait for that during 10 seconds.
If nothing is done, then, I would like to be able to exit the program.
My problem is that the function scanner block my program (until the user have pressed a key) and doesn't allow the program to execute the end.
Do you have any idea of what I could do/use instead of scanner? I am just a beginner in java so please, be indulgent with me.
import java.util.Scanner;
public class Test{
public Test(){
Scanner scan = new Scanner(System.in);
boolean first = true;
System.out.println("Press any key to start.\n");
for(int fr = 0; fr <11; fr++){
System.out.println(fr);
try{
Thread.sleep(1000);
} catch (Exception e) {
System.err.println("error -> "+e.getMessage()); // in case of exception, error message
}
if(fr == 10){
Default def = new Default();
}else if(scan.hasNext() == true){
//System.out.println("Hello");
User user = new User(); // or exit, it doesn't matter
}
}
}
}
Use a KeyListener.
First make a Component, give it the focus, and add a KeyListener.
Example code:
Component comp = new Componenet();
comp.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
System.out.print("Hello");
}
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
});
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.exit(0);
A possible solution is using a different thread to read user input from the scanner. Here is an example code:
Scanner scanner = new Scanner(System.in);
ExecutorService scannerExecutor = Executors.newSingleThreadExecutor();
Future<String> nextLineFuture = scannerExecutor.submit(scanner::nextLine);
/* For Java < 8:
Future<String> nextLineFuture = scannerExecutor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return scanner.nextLine();
}
});
*/
String input;
try {
input = nextLineFuture.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
input = "Nothing was entered";
}
catch (InterruptedException | ExecutionException e) {
// Handle the exception
return;
}
System.out.println(input);
However, you need to keep in mind some of the issues with this:
Even when nextLineFuture.get(...) throws TimeoutException, the nextLine call will still be running. If you later run scannerExecutor.submit(scanner::nextLine) again, the input will first be consumed by the previous call, so you should make sure to have a reference to the last Future created whose result hasn't been used yet.
Because of the issue above, this approach will not work if you need to use different scanner methods such as nextBoolean, nextInt, etc. You can, however, always use nextLine on the primary scanner and then parse the line manually (for example, by using yet another scanner)

Categories