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:
Thread th = new Thread(() -> {
try {
while(System.in.available() < 1) {
Thread.sleep(200);
}
System.in.read();
} catch (InterruptedException e) {
// sleep interrupted
} catch (IOException e) {
e.printStackTrace();
}
});
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:
public static void main(String[] args) throws InterruptedException, IOException {
PipedOutputStream stagingPipe = new PipedOutputStream();
PipedInputStream releasingPipe = new PipedInputStream(stagingPipe);
Thread stagingThread = new Thread(() -> {
try {
while(true) {
stagingPipe.write(System.in.read());
}
} catch (IOException e) {
e.printStackTrace();
}
});
stagingThread.setDaemon(true);
stagingThread.start();
Thread th = new Thread(() -> {
try {
releasingPipe.read();
} catch (InterruptedIOException e) {
// read interrupted
} catch (IOException e) {
e.printStackTrace();
}
});
th.start();
Thread.sleep(1000);
Thread.sleep(1000);
th.interrupt();
Thread.sleep(1000);
Thread.sleep(1000);
System.out.println(th.isAlive()); // Outputs false
}
But Wait! (Another Java API Fail)
Unfortunately, as pointed out by user Motowski, there exists a "Won't Fix" bug in the Java API implementation of PipedInputSteam
. So if you use the unmodified library version of PipedInputSteam
as shown above, it will sometimes trigger a long sleep via wait(1000)
. To work around the bug, Developers must make their own FastPipedInputStream
subclass as described here.
th.close();
no? – Stratfordonavon