我有一个读取用户输入并通过网络发送的线程。线程就像这样循环:
sin = new Scanner(System.in);
while (sin.hasNextLine()) {
if (this.isInterrupted())
break;
message = sin.nextLine();
// do processing...
}
但是当我尝试中断线程时,它不会退出hasNextLine()
方法。
我怎样才能真正退出这个循环?
答案 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()) {
...
}
}