Search code examples
javaloopstimer

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


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;
    }

Solution

  • 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.