【问题标题】:Time limit for an input inside a loop循环内输入的时间限制
【发布时间】:2018-11-03 19:12:35
【问题描述】:

我想实现一个用户需要在固定时间限制内输入的功能。我已经完成了这个答案。

Time limit for an input

此示例一次有效。当用户没有给出固定输入时,程序正在终止。但我试图在一个循环中多次使用它。每次我都需要检查用户提供的输入。请参阅我的 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 {
        //
    }
}

问题:按照我的逻辑,如果用户在5秒内输入res,那么responseString的值就是res,否则就是空值。这里 5 秒后仍在等待用户输入。

我的要求:如果用户在 5 秒内输入 res,那么它将适用于 //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

【问题讨论】:

  • 删除in.close(); - 一旦你关闭System.in,它就不会重新打开。
  • 与您的问题无关:您永远不应该在来自System.in 的输入上调用close。否则,您的玩家将永远无法回答问题 #2。
  • 我已将其删除。但问题仍然存在。
  • 当 5 秒结束时,空字符串将被分配给 responseString 。但是在这里,5 秒后,控制台仍在等待输入

标签: java input timertask


【解决方案1】:

这可以通过基于事件的模型来实现。为此,您需要两个线程(其中一个可以是主线程)。

第一个线程将接受来自 Scanner 的输入并将其添加到事件队列中(在我们的例子中,“事件”只是输入的字符串):

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

【讨论】:

  • 我对事件队列一无所知。我将在哪里添加这些代码,以及它是如何工作的。它似乎与我的代码不同。
  • 这是如何工作的 -> 1. 如果用户提供输入,则接受该输入,responseString = input,进行下一次迭代,2. 如果用户不提供输入,则停止接受输入,responseString = "",进入下一次迭代
  • poll 方法将返回队列中的第一件事(即扫描程序线程添加到其中的第一件事),如果在五秒内没有任何内容,则返回 null
  • 对不起,但它不适用于第二次迭代。在第一次迭代中,如果我输入 res 作为输入,它工作得很好,如果我不输入,则进入第二次迭代。如果我在第二次迭代中键入 res,它不起作用,总是返回 null。帮我修一下。谢谢
  • 第二次迭代不接受输入,总是返回 null。请修复它。
猜你喜欢
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 2011-08-16
  • 1970-01-01
  • 2019-06-15
  • 2013-07-26
  • 1970-01-01
  • 2012-10-18
相关资源
最近更新 更多