我试图用这个功能构建一个命令行界面:如果用户插入一个输入(在本例中是一个整数)需要15秒以上的时间,该函数会做出一个默认选择(0)。下面的代码是我到目前为止写的,它工作正常。
问题是我想添加一个新功能:如果用户写错了数字(
然而,当控制台打印消息时,计时器应该仍然运行,并在15秒后结束此循环,以防用户继续插入错误的数字。如果用户最终得到一个正确的数字,它应该立即打破循环。
这是我的代码,但我对如何添加功能没有明确的想法,因为我对未来的、可调用的和执行器功能相对较新。如果有人在这方面有更多的经验,我很乐意学习!
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;
}
下面是一个简化的较短版本,如果用户未键入内容,它将在n秒后超时:
private static final ExecutorService l = Executors.newFixedThreadPool(1);
private static String getUserInputWithTimeout(int timeout) {
Callable<String> k = () -> new Scanner(System.in).nextLine();
LocalDateTime start = LocalDateTime.now();
Future<String> g = l.submit(k);
while (ChronoUnit.SECONDS.between(start, LocalDateTime.now()) < timeout) {
if (g.isDone()) {
try {
String choice = g.get();
return choice;
} catch (InterruptedException | ExecutionException | IllegalArgumentException e) {
logger.error("ERROR", e);
g = l.submit(k);
}
}
}
logger.info("Timeout...");
g.cancel(true);
return null;
}
public static void main(String[] args) {
logger.info("Input the data in 10 seconds or less...");
String res = getUserInputWithTimeout(10); // 10s until timeout
if(res != null) {
logger.info("user response: [" + res + "]");
}
System.exit(0);
}
是的,所以你想做的是提交未来并调用未来#get(),并使用TimeUnit和Long参数来指示在放弃操作/执行之前要阻止的阈值。
值得注意的是,ThreadPoolExecutor不应该这样使用。它应该在方法之外定义并重新使用,然后在应用程序终止或不再需要时关闭。
private int getChoiceWithTimeout(int range){
Callable<Integer> callable = () -> new Scanner(System.in).nextInt();
ExecutorService service = Executors.newFixedThreadPool(1);
System.out.println("Enter your choice in 15 seconds :");
Future<Integer> inputFuture = service.submit(callable);
try {
return inputFuture.get(15, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException("Thread was interrupted", e);
} catch (ExecutionException e) {
throw new IllegalStateException("Something went wrong", e);
} catch (TimeoutException e) {
// tell user they timed out or do something
throw new IllegalStateException("Timed out! Do something here OP!");
} finally {
service.shutdown();
}
}
您可以通过使用带标签的break(done:
在下面给出的代码中)和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;
}
}
示例运行:不输入任何内容,该方法将在15秒后返回0
,与当前处理代码的方式相同
Enter your choice in 15 seconds :
0
另一个示例运行:一旦用户输入有效的数字,该方法将返回输入值;否则,它将继续请求有效输入,或在15秒后返回0
。
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
注意:使用标记的突破
不是强制性的,您可以用传统的突破
ing方式来替换它,但这需要您添加更多的代码行。
问题内容: 可以为用户输入设置计时器吗?等待10秒-进行下一个操作等。例如 问题答案: 不是开箱即用,不。通常,只有当另一个线程关闭基础流或到达输入的末尾时,Reader才会中断read()调用。 由于read()并非具有所有可中断性,因此这成为并发编程问题。知道超时的线程将需要能够中断正在尝试读取输入的线程。 本质上,读取线程将必须轮询Reader的ready()方法,而不是在没有要读取的内容时
可以为用户输入设置计时器吗?等待10秒钟-进行下一步操作等。我的意思是例如
我正在开发一个待办事项列表程序。 我想让用户可以输入日期、时间和关于。我已经知道日期了。我错过的是时间。 但我有很多例外。我错过了什么吗?
编辑问题以包括所需的行为、特定的问题或错误,以及重现问题所需的最短代码。这将帮助其他人回答这个问题。 我正在做一个待办事项列表程序。 我想让用户可以输入日期、时间和关于。我已经有日期了。我缺少的是时间。 但我有很多例外。我有什么遗漏吗?
问题内容: 我尝试创建一个计算器,但由于不知道如何获得用户输入而无法使它工作。 如何获得Java中的用户输入? 问题答案: 你可以根据要求使用以下任何选项。 Scanner class BufferedReader and InputStreamReader classes DataInputStream class 该类中的方法已被弃用。若要获取值,应将先前的解决方案与一起使用 Console
问题内容: 我有一个JComboBox的子类。我尝试使用以下代码添加一个键侦听器。 但是,这不能正确检测用户何时按下一个键。实际上根本没有调用它。我添加的这个监听器是否错误?还有其他添加方式吗? 问题答案: 关键事件不是在框本身上触发的,而是在其编辑器上触发的。您需要将keyListener添加到JComboBox的编辑器中,而不是直接添加到框中: 编辑:固定方法调用。