如何中断scanner.nextline()调用 [英] how to interrupt a scanner.nextline() call

查看:138
本文介绍了如何中断scanner.nextline()调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于中断读取系统的问题有很多线索。但我在这里寻找的是如何最好地编写我想要实现的内容的一些建议。

There are many threads on SO about interrupting reading the system.in but what I am looking for here is some kind of advice as to how to best code what I am trying to achieve.

我有一个getlogin()方法需要执行以下操作:要求用户输入所需的登录环境详细信息,如果6秒后用户没有输入有效值(实时或测试) )然后将userlogin变量设置为test并将其返回给调用者。

I have a getlogin() method that needs to do the following: ask a user to input the desired login environnement details, if after 6 seconds user have not input a valid value ("live" or "test") then set userlogin variable to "test" and return it to the caller.

我对getlogin()实现采取了以下方法:

I have taken the following approach for the getlogin() implementation:

1 - 启动两个执行以下操作的线程:
- thread1创建一个scanner对象然后调用scanner.nextline()并根据用户输入设置变量userlogin。在退出thread1之前中断thread2。
- thread2等待6秒,如果仍未设置userlogin,则为userlogin设置默认值。在退出thread2之前中断thread1。

1 - launch two threads which do the following: - thread1 creates a scanner object then calls scanner.nextline() and depending on user input set a variable userlogin. Interrupts thread2 before exiting thread1. - thread2 waits 6 seconds and if after that userlogin is still not set, then set a default value for userlogin. Interrupts thread1 before exiting thread2.

2 - 加入thread2以阻止主线程返回null userlogin

2 - join thread2 to stop main thread from returning a null userlogin

3 - return userlogin

3 - return userlogin

我遇到的问题是,当thread2调用thread1.interrupt时,scanner.inxtline()不会中断,这就是我不加入thread1的原因在步骤2中,主线程将挂起。
有没有办法在thread2中断后让thread1完成?或者这种方法是否完全过度,并且有一种更简单的方法来实现合同?

The problem I have with the approach is that scanner.nextline() does not interrupt when thread2 calls thread1.interrupt, which is why I do not join thread1 in step 2 as the main thread would hang. Is there a way to get thread1 to complete after thread2 interrupts it? Or else is this approach completely overkill and there is a much simpler way to achieve the contract?

推荐答案

最简单的解决方案是暴露读取线程中的基础流,并从超时线程关闭该流。这应该会中断读取并引发异常。处理此异常,您应该能够继续执行逻辑。唯一的问题是你将无法再次重复使用相同的流。不幸的是,没有简单的方法来处理阻塞系统调用的中断。

The simplest solution is to expose the underlying stream in the "reading" thread and close that stream from the timeout thread. This should interrupt the reading and raise an exception. Handle this exception and you should be able to proceed with your logic. The only gotcha is that you won't be able to re-use the same stream again. Unfortunately there is no easy way to deal with interruption of blocking system calls.

编辑:

遵循完全不同的推理方式;由于我们无法关闭输入流只是为了打断它,我能想到的唯一方法就是使用Robot类提供的编程用户输入功能。这是一个适合我的例子:

Following a completely different line of reasoning; given that we can't close the input stream just to interrupt it, the only way I can think of is to use the "programmatic user input" facilities offered by the Robot class. Here is an example which works out for me:

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变量为空。然后我们有一个检查,它执行必要的逻辑并设置适当的用户名。

The above code uses the logic that once that timeout has expired, we simulate a newline which will cause the "name" variable to be blank. Then we have a check which performs the necessary logic and sets the appropriate user name.

关于上述方法的问题是它:

The gotcha about the above approach is that it:


  • 使用机器人类AWT,因此可能无法与无头终端配合使用(?)

  • 假设焦点窗口是控制台窗口。如果焦点位于其他位置,则 ENTER 按键将为该窗口注册,而不是应用程序窗口。

  • Uses Robot class of AWT so might not play well with headless terminals (?)
  • Assumes that the focus window is the console window. If the focus is somewhere else, the ENTER key-press will be registered for that window as opposed to your application window.

希望这可以帮到你。我现在真的没有想法了。 :)

Hope this helps you out. I'm really out of ideas now. :)

这篇关于如何中断scanner.nextline()调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆