java - 终端中的数据循环打印可由用户输入终止
问题描述
我的任务是在终端打印货币汇率表,每分钟打印一次有延迟的表。在用户输入时,我将结束循环并返回海关终端菜单。如何做到这一点?
一般来说,我有一个问题要弄清楚如何获得无缝的用户体验。如果没有用户操作,我需要在终端中进行用户输入,并且仍然每分钟打印一次数据。最终,如果用户决定终止打印,如何完全终止整个数据打印循环?-> 运行标志 = ????;
它实际上是正确的方法吗?
我尝试了几种方法,不幸的是没有工作。
有谁能够帮我?
到目前为止,我只有以下代码。在循环中打印汇率的自定义方法:
private void printExchangeRateTable(final Map<String, Integer> storedExchangeRates){
boolean runFlag = true;
do {
printExchangeRates(storedExchangeRates);
println("Hit any key to stop loop");
Thread threadDelayer = new Thread(new Delayer());
Thread threadListeningUserInput = new Thread(new UserInputListener());
threadDelayer.start();
threadListeningUserInput.start();
runFlag = ????;
} while (runFlag);
}
延迟器对象
final class Delayer implements Runnable {
public static final long MILISECONDS = 1000L;
@Override
public void run(){
try {
Thread.sleep(60 * MILISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
用户输入监听器
class UserInputListener implements Runnable {
@Override
public void run() {
Scanner scanner = new Scanner(System.in);
val userInput = scanner.nextLine();
if(userInput != null) {
Thread.currentThread().interrupt();
}
}
}
解决方案
您可以使用 设置重复任务ScheduledExecutorService
,但在这里,将用户输入的读数发送到后台任务中要容易得多
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
CompletableFuture<String> userInput = CompletableFuture.supplyAsync(s::nextLine);
while(!userInput.isDone()) {
printData();
try {
userInput.get(1, TimeUnit.MINUTES);
}
catch(ExecutionException|InterruptedException ex) {} // handled after the loop
catch(TimeoutException ex) {
continue;
}
}
String input = userInput.join();
// handle input
}
private static void printData() {
System.out.println("data");
}
CompletableFuture.supplyAsync(s::nextLine)
将提交执行s.nextLine()
到后台任务。然后,循环将一直运行,直到后台任务完成,printData()
每分钟执行一次。这是通过which 来实现的,如果在指定时间后没有可用的结果userInput.get(1, TimeUnit.MINUTES)
,则会抛出一个。TimeoutException
这里continue
没有必要,因为循环无论如何都会继续,但我明确表示了。
其他可能的异常是在本质上处理的。中断不应该发生,但是通过进入下一次迭代,它可以用作甚至在时间之前刷新打印数据的信号。当一个发生时,当我们在循环之后的语句ExecutionException
中获得实际的用户输入时,将报告错误状态。join()
这个循环也可以合并到一个更大的循环中
Scanner s = new Scanner(System.in);
for(boolean quit = false; !quit; ) {
CompletableFuture<String> userInput = CompletableFuture.supplyAsync(s::nextLine);
while(!userInput.isDone()) {
printData();
try {
userInput.get(1, TimeUnit.MINUTES);
}
catch(ExecutionException|InterruptedException ex) {} // handled implicitly
catch(TimeoutException ex) {
continue;
}
}
String input = userInput.join();
// handle input
if(input.equals("exit")) quit = true;
}
推荐阅读
- javascript - 使用 Express.js 和 axios 的 HTTP PUT
- reactjs - 如何在现有的 react 组件中包含 ant design pro 组件
- javascript - 两个函数 JavaScript 之间的 SetInterval
- python - 线性化 LP 程序中的非线性约束
- android - 从特定片段导航到另一个片段后无法使用后退按钮返回
- perl - 使用 Perl 和 XML::LibXML::PrettyPrint,如何保留内联处理指令周围的空白?
- c# - 我可以使用正则表达式仅用两个冒号替换两个或多个冒号吗
- floating-point - 0.1 是一个近似值,但是当我们添加 0.1 和 0.2 时,为什么不在幕后进行四舍五入呢?
- html - 在 html 中的 Select Tag 中更改多个选项选择焦点颜色
- android-studio - 你如何在颤振中安装密钥库?