2

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;
    }
Raj Gupta
  • 35
  • 4
  • The code you have written repeatedly asks for input for 3.5 seconds; is that what you want? – Scott Hunter Sep 02 '19 at 21:23
  • No, I want it to stop asking for input and skip the code after 3.5 seconds – Raj Gupta Sep 02 '19 at 21:25
  • Possible duplicate of [how to read from standard input non-blocking?](https://stackoverflow.com/questions/7872846/how-to-read-from-standard-input-non-blocking) – Fureeish Sep 03 '19 at 00:39

1 Answers1

3

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.

second
  • 4,069
  • 2
  • 9
  • 24
  • Hey, I really appreciate the effort you put in trying to help me. However, I'm quite new (just started AP CS) and wanted further understanding on what this code is and does. – Raj Gupta Sep 03 '19 at 00:20
  • Yes, we haven't learned static yet (which is surprising, I know). So like, do I make another class to put the first block of code in or do I do it below all my code? And I started this project before I learned Eclipse, so its in blueJ, will it still work? And sorry for asking you all this, but could you please elaborate on how this works? – Raj Gupta Sep 03 '19 at 00:29
  • The `static` is not really relevant in this case (I just used it as I created this as an [`inner class`](https://www.javatpoint.com/static-nested-class) next to the main method). Feel free to create a `public class` (in its own file) instead. -- I've never used `blueJ` but its just basic java code, not really related to any `IDE`. – second Sep 03 '19 at 00:30
  • I put it under my class and it says modifier static not allowed here – Raj Gupta Sep 03 '19 at 00:36
  • I have added a main class (`Test`), now you can simply copy it. – second Sep 03 '19 at 00:36
  • [link](https://pastebin.com/KEB3gWsx) I modified it to this and when it returns input after time runs out it gives me a null pointer exception, how would I fix this? @second – Raj Gupta Sep 03 '19 at 01:06
  • Integer is an object, that might be null. The [`unboxing`](https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) to a primitive int causes the `NullPointerExcetpion`, because a primitive can't be null. Add an `if (input == null) return -1` (or any other indicator that the user did not input anything) or change the return type of the method to `Integer`. – second Sep 03 '19 at 01:08