Ограничение по времени для входа внутри цикла - PullRequest
0 голосов
/ 03 ноября 2018

Я хочу реализовать функцию, в которой пользователю нужно вводить данные в фиксированный срок. Я прошел через этот ответ.

Лимит времени для входа

Этот пример работает один раз. Когда пользователь не вводит фиксированные данные, программа завершается. Но я пытаюсь использовать его несколько раз в цикле. Мне нужно каждый раз проверять, какой пользователь дает ввод. См. Мой класс InputTimer, модифицированный из этого поста.

InputTimer.java

public class InputTimer {
    private String str = "";
    public String responseString = "";
    private BufferedReader in;
    TimerTask task = new TimerTask() {
        public void run() {
            if (str.equals("")) {
                responseString = "";
            }
        }
    };

    public void getInput() throws Exception {
        Timer timer = new Timer();
        timer.schedule(task, 5 * 1000);

        in = new BufferedReader(new InputStreamReader(System.in));
        str = in.readLine();
        timer.cancel();
        responseString = str;
    }
}

Я пытался реализовать это в другом классе внутри цикла:

for(int i=0; i<5; i++){
    System.out.println("Enter res in 5 sec: ");
    InputTimer inputTimer = new InputTimer();
    try {
        inputTimer.getInput();
    } catch (Exception e) {
        e.printStackTrace();
    }
    String responseString = inputTimer.responseString;
    if(responseString.equals("res")){
        //User typed res
    } else {
        //
    }
}

Проблема: Согласно моей логике, если пользовательский тип res через 5 секунд, тогда значение responseString будет res, в противном случае это будет пустое значение. Вот через 5 сек все еще жду ввода пользователя.

Мое требование: Если пользователь введет res в течение 5 секунд, то он будет работать для //User typed res задач и перейдет к следующей итерации. Если в течение 5 секунд пользователь ничего не наберет, пользователь не сможет ввести данные (опция ввода пользователя пропадет), тогда значение responseString станет пустым, в противном случае блок будет выполнен, а затем снова перейдет к следующему итерации.

Пожалуйста, помогите мне найти решение этого сценария.

Вот еще одна попытка решения Joe C. Это работает на один раз. Проверьте код:

public class test {
    private static BlockingQueue<String> lines = new LinkedBlockingQueue<>();
    public static String inputTimer() throws InterruptedException {

        return lines.poll(5, TimeUnit.SECONDS);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            String tmp = "";
            try {
                System.out.print("Iteration " + i + ": Enter any in 5 sec: ");
                Thread t = new Thread(() -> {
                Scanner s = new Scanner(System.in);
                while (true) {
                    lines.add(s.nextLine());
                }
            });
            t.setDaemon(true); 
            t.start();
                tmp = inputTimer();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("You entered: " + tmp);
        }
    }
}

Выходной журнал:

Iteration 0: Enter any in 5 sec: xx
You entered: xx
Iteration 1: Enter any in 5 sec: xx
You entered: null
Iteration 2: Enter any in 5 sec: xx
You entered: null
Iteration 3: Enter any in 5 sec: xx
You entered: xx
Iteration 4: Enter any in 5 sec: You entered: xx

1 Ответ

0 голосов
/ 03 ноября 2018

Этого можно достичь с помощью модели на основе событий. Для этого вам понадобятся два потока (один из них может быть основным).

Первый поток примет ввод от сканера и добавит его в очередь событий (в нашем случае «событие» - это просто строка, которая вводится):

private BlockingQueue<String> lines = new LinkedBlockingQueue<>();

Запустите указанный поток в вашем основном методе:

Thread t = new Thread(() -> {
    Scanner s = new Scanner(System.in);
    while (true) {
        lines.add(s.nextLine());
    }
});
t.setDaemon(true); // so that this thread doesn't hang at the end of your program
t.start();

Затем, когда вы хотите получить ввод, вы можете получить его из очереди с таймаутом:

return lines.poll(5, TimeUnit.SECONDS);
...