最简单的解决方案是在“读取”线程中公开底层流,并从超时线程中关闭该流。这应该会中断阅读并引发异常。处理这个异常,你应该能够继续你的逻辑。唯一的问题是您将无法再次重复使用相同的流。不幸的是,没有简单的方法来处理阻塞系统调用的中断。
编辑:
遵循完全不同的推理路线;鉴于我们不能仅仅为了中断输入流而关闭它,我能想到的唯一方法是使用 Robot 类提供的“程序化用户输入”工具。这是一个对我有用的例子:
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
public class ConsoleTest {
/**
* @param args
*/
public static void main(String[] args) {
new TimeoutThread().start();
new ReaderThread().start();
}
}
class ReaderThread extends Thread {
@Override
public void run() {
System.out.print("Please enter your name: ");
try(Scanner in = new Scanner(System.in)) {
String name = in.nextLine();
if(name.trim().isEmpty()) {
name = "TEST"; // default user name
}
System.out.println("Name entered = " + name);
}
}
}
class TimeoutThread extends Thread {
@Override
public void run() {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(5));
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
} catch(Exception e) {
e.printStackTrace();
}
}
}
上面的代码使用的逻辑是,一旦超时过期,我们模拟一个换行符,这将导致“name”变量为空。然后我们有一个检查,它执行必要的逻辑并设置适当的用户名。
关于上述方法的问题在于:
- 使用 AWT 的 Robot 类,因此可能无法与无头终端(?)
- 假设焦点窗口是控制台窗口。如果焦点在其他地方,
ENTER
则将为该窗口而不是您的应用程序窗口注册按键。
希望这可以帮助你。我现在真的没主意了。:)