首页 > 解决方案 > Java中超时的用户输入

问题描述

我正在尝试使用此功能构建命令行界面:如果用户花费超过 15 秒来插入输入(在本例中为整数),则该函数会做出默认选择 (0)。下面的代码是我到目前为止写的,它工作正常。

问题是我想添加一个新功能:如果用户输入错误的数字(<0 或 >range),控制台应该打印类似("Wrong choice, you have to pick an integer between 0 - "+ range);

但是,当控制台打印消息时,计时器应该仍在运行并在 15 秒后结束此循环,以防用户不断插入错​​误的数字。如果用户最终得到一个正确的数字,它应该立即中断循环。

这是我的代码,但我对如何添加功能没有明确的想法,因为我对 Future、Callable 和 Executor 功能相对较新。如果有人对此有更多经验,我将很高兴学习!

private int getChoiceWithTimeout(int range){
       Callable<Integer> k = () -> new Scanner(System.in).nextInt();
       Long start= System.currentTimeMillis();
       int choice=0;
       ExecutorService l = Executors.newFixedThreadPool(1);  ;
       Future<Integer> g;
       System.out.println("Enter your choice in 15 seconds :");
       g= l.submit(k);
       while(System.currentTimeMillis()-start<15*1000 && !g.isDone()){
           // Wait for future
       }
       if(g.isDone()){
           try {
               choice=g.get();
           } catch (InterruptedException | ExecutionException e) {
               e.printStackTrace();
           }
       }
       g.cancel(true);
       return choice;
    }

标签: javatimeoutjava.util.scannerfuturecallable

解决方案


您可以使用标记的 breakdone:在下面给出的代码中)和boolean变量(valid在下面给出的代码中)来跟踪输入是否有效。

import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getChoiceWithTimeout(10));
    }

    static int getChoiceWithTimeout(int range) {
        Callable<Integer> k = () -> new Scanner(System.in).nextInt();
        Long start = System.currentTimeMillis();
        int choice = 0;
        boolean valid;
        ExecutorService l = Executors.newFixedThreadPool(1);
        Future<Integer> g;
        System.out.println("Enter your choice in 15 seconds :");
        g = l.submit(k);
        done: while (System.currentTimeMillis() - start < 15 * 1000) {
            do {
                valid = true;
                if (g.isDone()) {
                    try {
                        choice = g.get();
                        if (choice >= 0 && choice <= range) {
                            break done;
                        } else {
                            throw new IllegalArgumentException();
                        }
                    } catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
                        System.out.println("Wrong choice, you have to pick an integer between 0 - " + range);
                        g = l.submit(k);
                        valid = false;
                    }
                }
            } while (!valid);
        }

        g.cancel(true);
        return choice;
    }
}

示例运行:不要输入任何内容,该方法将0在 15 秒后返回,就像它当前对您的代码所做的那样

Enter your choice in 15 seconds :
0

另一个示例运行:用户输入一个有效数字后,该方法将返回输入的值;否则,它将0在 15 秒后继续询问有效输入或返回。

Enter your choice in 15 seconds :
a
Wrong choice, you have to pick an integer between 0 - 10
12
Wrong choice, you have to pick an integer between 0 - 10
5
5

注意:使用标签break不是强制性的,您可以将其替换为传统的breaking 方式,但这需要您添加更多代码行。


推荐阅读