是否可以中断Scanner.hasNext()

时间:2013-10-02 06:00:13

标签: java multithreading io

我有一个读取用户输入并通过网络发送的线程。线程就像这样循环:

sin = new Scanner(System.in);

while (sin.hasNextLine()) {
    if (this.isInterrupted())
        break;

    message = sin.nextLine();

    // do processing...        
}

但是当我尝试中断线程时,它不会退出hasNextLine()方法。

我怎样才能真正退出这个循环?

4 个答案:

答案 0 :(得分:5)

尝试使用以下方法替换sin.hasNextLine。 除非该流上有可用数据,否则背后的想法是不进入阻塞读取操作。

前一段时间我遇到了同样的问题,这就解决了这个问题。 基本上,当你在一个线程和另一个线程上执行System.in.read()时,你试图打断它,除非你按Enter,否则它将无效。您可能认为按下任何字符都应该有效,但事实并非如此,因为看起来os(或jvm的硬件抽象层)中的读操作只返回完整的行。

即使System.in.available(),也不会返回非零值,除非您据我所知按Enter

private boolean hasNextLine() throws IOException {
    while (System.in.available() == 0) {
        // [variant 1
        try {
            Thread.currentThread().sleep(10);
        } catch (InterruptedException e) {
            System.out.println("Thread is interrupted.. breaking from loop");
            return false;
        }// ]

        // [variant 2 - without sleep you get a busy wait which may load your cpu
        //if (this.isInterrupted()) {
        //    System.out.println("Thread is interrupted.. breaking from loop");
        //    return false;
        //}// ]
    }
    return sin.hasNextLine();
}

答案 1 :(得分:0)

您可以使用布尔值,然后在想要停止while循环时将其设置为false

sin = new Scanner(System.in);
boolean = runLoop = true;
while (sin.hasNextLine() && runLoop) {
    if (this.isInterrupted())
        break;

    message = sin.nextLine();

    // do processing...        
}

答案 2 :(得分:-1)

我的测试似乎不支持您的发现。它按预期工作!

我写了以下演示代码

public class DemoThread extends Thread {

    Scanner sin = new Scanner(System.in);

    @Override
    public void run() {
        while (sin.hasNextLine()) {
            if(this.isInterrupted()) {
                System.out.println("Thread is interrupted.. breaking from loop");
                break;
            }

            String message = sin.nextLine();
            System.out.println("Message us " + message);

            // do processing...
        }
    }

    public static void main(String args[]) throws InterruptedException {

        DemoThread thread = new DemoThread();
        thread.start();
        Thread.sleep(5000);
        thread.interrupt();

    }

}

,输出

a
Message us a
s
Message us s
asd
Thread is interrupted.. breaking from loop

所以请再次检查。此外,如果您对输出asd感到困惑,那么它是前一个循环迭代中的字符串输入,而该线程未被中断。如果您不想要,那么

if(!this.isInterrupted()) {
    String message = sin.nextLine(); 
}

Why is this happening?

让我们说在一个迭代线程中没有被中断所以它进入while循环(hasNext()因为前一次迭代中的String读取而通过)。它检查线程是否被中断(让我们说它不是在这个时间点)并转到下一行(从stdinput扫描新字符串)。现在让我们说线程被中断了。你的程序会等到你输入一些字符串(你必须在控制台中输入)。因此,即使线程未被破坏,也会读取字符串,并且此字符串将用于评估hasNext()操作(将评估为true),并且上下文将进入while循环。这将看到线程被中断并将中断。

要避免这种情况,你需要在if(!this.isInterrupted())语句中读取字符串。请参阅上面的代码。

答案 3 :(得分:-1)

通常,如果你想让一个线程无限期地运行,但仍然可以打断它,你可以这样做:

while (!Thread.currentThread().isInterrupted()) {
  while (scanner.hasNextLine()) {
    ...
  }
}