Java: how to abort a thread reading from System.in
Solution 1:
Heinz Kabutz's newsletter shows how to abort System.in
reads:
import java.io.*;
import java.util.concurrent.*;
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()) {
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;
}
}
public class ConsoleInput {
private final int tries;
private final int timeout;
private final TimeUnit unit;
public ConsoleInput(int tries, int timeout, TimeUnit unit) {
this.tries = tries;
this.timeout = timeout;
this.unit = unit;
}
public String readLine() throws InterruptedException {
ExecutorService ex = Executors.newSingleThreadExecutor();
String input = null;
try {
// start working
for (int i = 0; i < tries; i++) {
System.out.println(String.valueOf(i + 1) + ". loop");
Future<String> result = ex.submit(
new ConsoleInputReadTask());
try {
input = result.get(timeout, unit);
break;
} catch (ExecutionException e) {
e.getCause().printStackTrace();
} catch (TimeoutException e) {
System.out.println("Cancelling reading task");
result.cancel(true);
System.out.println("\nThread cancelled. input is null");
}
}
} finally {
ex.shutdownNow();
}
return input;
}
}
Now, I don't know whether this approach leaks, isn't portable or has any non-obvious side-effects. Personally, I would be reluctant to use it.
You might be able to do something with NIO channels and file descriptors - my own experiments with them didn't yield any results.
Solution 2:
How about...
private static BufferedReader stdInCh = new BufferedReader(
new InputStreamReader(Channels.newInputStream((
new FileInputStream(FileDescriptor.in)).getChannel())));
A thread where stdInch.readline()
is called is now interruptible and the readline() will throw a java.nio.channels.ClosedByInterruptException
.