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

时间:2018-03-30 17:18:52

标签: java

我有一个问题如何实现这里找到的各种变体:

Set Time Limit on User Input (Scanner) Java

就我而言,如果在保持程序存活的同时达到Timelimit,我想忽略输入。

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秒内给出输入(并且它有效),则循环结束并且任务被取消,这是完美的。但是,如果输入无效并且计时器结束,我希望它停止询问输入并跳到这里“" REACHED HERE"位置。这甚至可能吗?

1 个答案:

答案 0 :(得分:2)

正如@Sedrick所提到的,对此最简单的解决方案是第二个线程。问题是从<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.SplitPane?> <?import javafx.scene.layout.AnchorPane?> <SplitPane dividerPositions="0.29797979797979796" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1"> <items> <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" /> <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" /> </items> </SplitPane> 读取是阻止的。很明显,您链接的示例解决了System.in的问题,但这对您的情况来说太极端了。

另一个旋转可能是使用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!"); 作为deque的代理。但是,在线程中,来自System.in的读取将始终是阻塞的 - 没有干净的方法来中断线程,缺少System.in

这可以稍微改进一下。首先,如果线程被标记为守护程序线程,则允许JVM在其周围关闭。例如。如果System.exit()方法完成,JVM也会干净地退出:

main()

但是,通过使用Thread thread = new Thread(() -> { ... }); thread.setDaemon(true); thread.start(); ,可以轮询等待输入。这样就可以干净地中断线程:

InputStream.available()

看起来用户在没有换行符的情况下键入几个字母会有一些风险。目前仍然会挂起,但这并没有发生在Windows上 - 显然命令窗口的数据只是逐行释放到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();