不带System.exit的有效Java输入的时间限制

不带System.exit的有效Java输入的时间限制,java,Java,我有一个问题,如何实现这里发现的内容的变化: 在我的例子中,如果在保持程序活动的同时达到了时间限制,我希望忽略输入 String str = ""; TimerTask task = new TimerTask(){ public void run(){ if(str.equals("")){ System.out.println("No Valid Input detected"); //TimerTask should end here a

我有一个问题,如何实现这里发现的内容的变化:

在我的例子中,如果在保持程序活动的同时达到了时间限制,我希望忽略输入

String str = "";
TimerTask task = new TimerTask(){
  public void run(){
     if(str.equals("")){
         System.out.println("No Valid Input detected");
         //TimerTask should end here along with the Input
         //Other example has System.exit which will also terminate the 
         //entire program
     }else {
         // still keep the program alive. The condition itself isn't 
         //important.
     }
}

Timer timer = new Timer();
timer.schedule(task, 10*1000);
Scanner scanner = new Scanner(System.in);

do{
      System.out.println("Type a message");
      str = scanner.nextLine();
}while(!str.equals("hello"));

timer.cancel();    

REACHED HERE!

如果输入在10秒内给出(并且有效),循环结束,任务取消,这是完美的。但是,如果输入无效且计时器结束,我希望它停止请求输入并跳到“到达此处”位置。这可能吗?

正如@Sedrick所提到的,解决这个问题的最简单方法是使用第二个线程。问题是从
系统中读取
会阻塞。显然,您链接的示例使用
System.exit()
解决了这个问题,但这对于您的情况来说太极端了

另一种方法可能是使用
Deque
(双端队列)中继输入,并在那里设置超时:

BlockingDeque<String> deque = new LinkedBlockingDeque<>();

new Thread(() -> {
    Scanner scanner = new Scanner(System.in);
    String input;
    do {
        System.out.println("Type a message");
        input = scanner.nextLine();
        deque.add(input);
    } while (!input.equals("hello"));
}).start();

String str;
do {
    str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));

System.out.println("REACHED HERE!");
但是,通过使用
InputStream.available()
,可以轮询等待的输入。这样就可以干净地中断线程:

BlockingDeque<String> deque = new LinkedBlockingDeque<>();

Thread thread = new Thread(() -> {
    Scanner scanner = new Scanner(System.in);
    String input;
    try {
        do {
            if (System.in.available() > 0) {
                input = scanner.nextLine();
                deque.add(input);
            } else
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    System.err.println("Thread stopped");
                    break;
                }
        } while (true);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
});
thread.start();

System.out.println("Type a message");
String str;
do {
    str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));

System.out.println("REACHED HERE!");

thread.interrupt();
BlockingDeque deque=newlinkedblockingdeque();
线程=新线程(()->{
扫描仪=新的扫描仪(System.in);
字符串输入;
试一试{
做{
if(System.in.available()>0){
输入=scanner.nextLine();
添加(输入);
}否则
试一试{
睡眠(50);
}捕获(中断异常例外){
System.err.println(“线程停止”);
打破
}
}虽然(正确);
}捕获(IOEX异常){
例如printStackTrace();
}
});
thread.start();
System.out.println(“键入消息”);
字符串str;
做{
str=deque.poll(10,时间单位:秒);
}而(str!=null&!str.equals(“hello”);
System.out.println(“到达这里!”);
thread.interrupt();

用户在没有换行符的情况下键入几个字母似乎有一定的风险。目前,这仍然会挂起,但这并没有发生在Windows上-显然,来自命令窗口的数据只会发布到
系统中。在
逐行中。

可能重复的Awesome,我没有想到使用Deque。谢谢,还有一个问题。看起来,如果发生超时,扫描程序线程将继续运行。有没有一种优雅的方法可以迫使它关闭?我之所以想这样做是因为我担心它的副作用。我想把所有代码放在另一个while循环中。因此,每当我们输入正确的答案或没有输入正确的答案时,它就会重新启动整个过程。但是如果扫描器的线程从未关闭,我不确定它是否每次都会创建一个新线程(从未关闭),或者它是否会重用当前的活动线程(如果有)。好的方面。。。想法是只启动一次线程,然后重复使用
deque
进行多次读取。但你是对的,如果你想释放线程,它仍然不容易。看看上面的扩展答案,有几个选项可以改进这一点。
BlockingDeque<String> deque = new LinkedBlockingDeque<>();

Thread thread = new Thread(() -> {
    Scanner scanner = new Scanner(System.in);
    String input;
    try {
        do {
            if (System.in.available() > 0) {
                input = scanner.nextLine();
                deque.add(input);
            } else
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    System.err.println("Thread stopped");
                    break;
                }
        } while (true);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
});
thread.start();

System.out.println("Type a message");
String str;
do {
    str = deque.poll(10, TimeUnit.SECONDS);
} while (str != null && !str.equals("hello"));

System.out.println("REACHED HERE!");

thread.interrupt();