If I start reading from System.in
, it will block the thread until it gets data. There is no way to stop it. Here are all the ways that I've tried:
- Interrupting the thread
- Stopping the thread
- Closing
System.in
- Calling
System.exit(0)
does indeed stop the thread, but it also kills my application so not ideal. - Entering a char into the console makes the method return, but I can't rely on user input.
Sample code that does not work:
public static void main(String[] args) throws InterruptedException {
Thread th = new Thread(() -> {
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
});
th.start();
Thread.sleep(1000);
System.in.close();
Thread.sleep(1000);
th.interrupt();
Thread.sleep(1000);
th.stop();
Thread.sleep(1000);
System.out.println(th.isAlive()); // Outputs true
}
When I run this code, it will output true
and run forever.
How do I read from System.in
in an interruptible way?
You should design the run method so that it can determine for itself when to terminate. Calling stop() or similar methods upon the thread would be inherently unsafe.
However, there still remains the question of how to avoid blocking inside System.in.read? To do that you could poll System.in.available until it returns > 0 prior to reading.
Example code:
Of course, it is generally considered favorable to use a blocking IO method rather than polling. But polling does have its uses; in your situation, it allows this thread to exit cleanly.
A Better Approach:
A better approach that avoids polling would be to restructure the code so that any Thread you intend to kill is not allowed direct access to
System.in
. This is because System.in is an InputStream that should not be closed. Instead the main thread or another dedicated thread will read from System.in (blocking) then write any contents into a buffer. That buffer, in turn, would be monitored by the Thread you intend to kill.Example code:
I've written a wrapper InputStream class that allows to be interrupted:
Adjust the
Thread.yield()
to sleep as long as the maximum latency you can accept and prepare for some exceptions when interrupting, but apart from that it should work fine.