Java 终端中的数据循环打印可由用户输入终止

Java 终端中的数据循环打印可由用户输入终止,java,concurrency,terminal,Java,Concurrency,Terminal,我的任务是在终端中打印货币汇率表,并每分钟延迟打印一次。在用户输入时,我将结束循环并返回海关终端菜单。如何做到这一点 总的来说,我有一个问题需要弄清楚如何拥有无缝的用户体验。我需要在终端中有用户输入,如果没有用户操作,仍然每分钟打印数据。最后,如果用户决定终止打印,那么如何终止整个数据打印循环?->runFlag= 这真的是正确的方法吗 我尝试过几种方法,但不幸的是,这些方法一直在起作用 有人能帮我吗 到目前为止,我只有以下代码。在循环中打印汇率的自定义方法: private void prin

我的任务是在终端中打印货币汇率表,并每分钟延迟打印一次。在用户输入时,我将结束循环并返回海关终端菜单。如何做到这一点

总的来说,我有一个问题需要弄清楚如何拥有无缝的用户体验。我需要在终端中有用户输入,如果没有用户操作,仍然每分钟打印数据。最后,如果用户决定终止打印,那么如何终止整个数据打印循环?->runFlag=

这真的是正确的方法吗

我尝试过几种方法,但不幸的是,这些方法一直在起作用

有人能帮我吗

到目前为止,我只有以下代码。在循环中打印汇率的自定义方法:

private void printExchangeRateTable(最终地图存储dexChangeRates){
布尔runFlag=true;
做{
打印汇率(存储汇率);
println(“按任意键停止循环”);
线程延迟器=新线程(新延迟器());
Thread threadListeningUserInput=新线程(新的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();
        }
    }
}

你可以试试这个。我使用与您相同的逻辑读取用户输入,但对于打印,我将使用计时器(此处计划每1秒运行一次,但您可以更改)。管理计时器更容易,可以从另一个线程取消

public class Main {
public static void main(String[] args) {
    Thread inputListener = new Thread(new UserInputListener());
    inputListener.start();
}

static class MyTimerTask extends TimerTask
{
    public void run()
    {
        System.out.println("some output");
    }
}

static class UserInputListener implements Runnable {
    @Override
    public void run()  {
        Timer timer = new Timer();
        TimerTask task = new MyTimerTask();
        timer.schedule(task, 0, 1000);
        Scanner scanner = new Scanner(System.in);
        scanner.nextLine();
        timer.cancel();
    }
  }
}

首先,您需要两个线程,但不必创建两个线程-您可以使用主线程进行用户输入,并在程序开始时启动另一个线程,该线程将每分钟打印货币汇率

每个线程内部都有一个无限(或标记控制)循环。但是,与其自己管理,我建议您使用
ScheduledExecutorService
,否则您将很难中断线程

以下是一个例子:

import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Example {

    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleWithFixedDelay(Example::printData, 1, 1, TimeUnit.MINUTES);

        Scanner scanner = new Scanner(System.in);

        while (true) {
            String userInput = scanner.nextLine();

            if (userInput.equals("exit")) {
                break;
            }
        }

        executor.shutdown();
    }

    private static void printData() {
        System.out.println("data");
    }

}
如果没有其他用户输入要处理,并且它仅用于停止后台线程,则此线程中根本不需要循环,您可以将其简化为:

public static void main(String[] args) {
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleWithFixedDelay(Example::printData, 1, 1, TimeUnit.MINUTES);

    Scanner scanner = new Scanner(System.in);
    scanner.nextLine();
    executor.shutdown();
}

您可以使用设置一个重复任务,但是在这里,将用户输入的读数发送到后台任务要容易得多

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

不要使用
java.util.Timer
。遗憾的是,这个东西还没有标记为不推荐。改用a,例如。
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;
}