I am using a multi threaded environment were one Thread is constantly listening for user input by repeatedly calling scanner.nextLine()
.
To end the application, this runloop is stopped by another thread, but the listening thread won't stop until a last user input was made (due to the blocking nature of nextLine()
).
Closing the stream seems not to be an option since I am reading from System.in
, which returns an InputStream
that is not closable.
Is there a way to interrupt the blocking of scanner, so that it will return?
thanks
This article describes an approach to avoiding blocking when reading. It gives the code snippet, which you could amend as I indicate in a comment.
import java.io.*;
import java.util.concurrent.Callable;
public class ConsoleInputReadTask implements Callable<String> {
public String call() throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("ConsoleInputReadTask run() called.");
String input;
do {
System.out.println("Please type something: ");
try {
// wait until we have data to complete a readLine()
while (!br.ready() /* ADD SHUTDOWN CHECK HERE */) {
Thread.sleep(200);
}
input = br.readLine();
} catch (InterruptedException e) {
System.out.println("ConsoleInputReadTask() cancelled");
return null;
}
} while ("".equals(input));
System.out.println("Thank You for providing input!");
return input;
}
}
You could either use this code directly, or write a new closable InputStream class, wrapping up the logic described in this article.
Sure. Use a nuke. Call System.exit(0)
at the end of your main thread. This will murder everything. Even the active thread waiting in System.in.
The problem is that System.in is a traditional input stream with blocking, and when it's blocking the thread is marked as running. You cannot interrupt it. So whatever thread you are using to read the System.in is calling read and the read will block the thread. You can coax some of this stuff with a bunch of tricks avoid calling read except in those cases when we can be sure there will be no block and then constantly poll. But, there's no real way around the problem that any attempt to read that will lock your thread and no amount of closing underlying streams or interrupting or stopping the thread will save you. But, if you murder the entire vm... the thread will die.
Obviously you need to make sure the rest of the threads have properly exited and it's just that one stupid I want to be able to respond to typed input thread that is the last hanger-on. But, if that's totally the case the correct answer is to exit, or at least, basically the only answer that'll work without burning clock-cycles for no reason and let the program terminate.
来源:https://stackoverflow.com/questions/4983065/how-to-interrupt-java-util-scanner-nextline-call