Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以中断Scanner.hasNext()_Java_Multithreading_Io - Fatal编程技术网

Java 是否可以中断Scanner.hasNext()

Java 是否可以中断Scanner.hasNext(),java,multithreading,io,Java,Multithreading,Io,我有一个线程可以读取用户输入并通过网络发送。线程位于如下所示的循环中: sin = new Scanner(System.in); while (sin.hasNextLine()) { if (this.isInterrupted()) break; message = sin.nextLine(); // do processing... } while (!Thread.currentThread().isInterrupte

我有一个线程可以读取用户输入并通过网络发送。线程位于如下所示的循环中:

sin = new Scanner(System.in);

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

    message = sin.nextLine();

    // do processing...        
}
while (!Thread.currentThread().isInterrupted()) {
  while (scanner.hasNextLine()) {
    ...
  }
}
但是当我试图中断线程时,它不会退出
hasNextLine()
方法


我如何才能真正退出这个循环?

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

我编写了以下演示代码

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(); 
}

假设在一次迭代中,线程没有被中断,因此它进入while循环(hasNext()由于在上一次迭代中读取的字符串而通过)。它检查线程是否被中断(假设它不在此时),并转到下一行(从stdinput扫描新字符串)。现在让我们假设线程被中断。您的程序将等待您输入一些字符串(您必须在控制台中按enter键)。因此,即使线程是inetrrupted,也将读取字符串,该字符串将用于计算hasNext()操作(该操作的计算结果将为true),并且上下文将进入while循环。在这里,它将看到线程被中断并将中断


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

通常,如果您想让线程无限期地运行,但仍然能够中断它,您可以这样做:

sin = new Scanner(System.in);

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

    message = sin.nextLine();

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

尝试用以下方法替换
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();
}

如果要停止while循环,可以使用布尔值,然后将其设置为false

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

    message = sin.nextLine();

    // do processing...        
}

您使用的是什么java/os?除非按键盘上的enter键,否则线程不会中断(对于本
系统,在
示例中)。基本上,您希望在用户不按enter键的情况下中断它。当您中断线程时,所发生的一切就是设置中断标志。线程不会提前退出hasNextLine方法。to Csoriu:是的,我有相同的行为线程不会中断,除非您在键盘上按enter键(当使用System.in作为扫描仪的输入时)。基本上,您希望在用户不按enter键的情况下中断它。在这种情况下,可能需要一个do,而循环会更有意义。只需跳过第一次迭代,按条件执行即可。。虽然(sin.hasNextLine()&&!this.isInterrupted())但它并不能解决问题-该线程仍在hasNextLine()调用中被阻塞…谢谢,我会尝试的。但不管怎么说,这似乎很尴尬,我不敢相信没有更干净的方法来使用
系统。在
中,我还没有找到其他方法。但考虑到这是一个低性能的操作(从控制台读取),让
睡眠就可以了。此外,您可以将该值增加到50或100,以查看它是否会以某种方式影响您的操作。我想不会的。