如何中断System.in上的读取? [英] How to interrupt reading on System.in?
问题描述
如果我从System.in
开始读取,它将阻塞线程,直到获取数据为止.没有办法阻止它.这是我尝试过的所有方法:
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:
- 中断线程
- 停止线程
- 关闭
System.in
- 调用
System.exit(0)
确实确实会停止线程,但也会杀死我的应用程序,因此不理想. - 在控制台中输入一个字符会使方法返回,但是我不能依赖用户输入.
- 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.
无效的示例代码:
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
}
运行此代码时,它将输出true
并永远运行.
When I run this code, it will output true
and run forever.
如何以一种可中断的方式读取System.in
?
How do I read from System.in
in an interruptible way?
推荐答案
我编写了一个包装器InputStream类,该类可以被中断:
I've written a wrapper InputStream class that allows to be interrupted:
package de.piegames.voicepi.stt;
import java.io.IOException;
import java.io.InputStream;
public class InterruptibleInputStream extends InputStream {
protected final InputStream in;
public InterruptibleInputStream(InputStream in) {
this.in = in;
}
/**
* This will read one byte, blocking if needed. If the thread is interrupted while reading, it will stop and throw
* an {@link IOException}.
*/
@Override
public int read() throws IOException {
while (!Thread.interrupted())
if (in.available() > 0)
return in.read();
else
Thread.yield();
throw new IOException("Thread interrupted while reading");
}
/**
* This will read multiple bytes into a buffer. While reading the first byte it will block and wait in an
* interruptable way until one is available. For the remaining bytes, it will stop reading when none are available
* anymore. If the thread is interrupted, it will return -1.
*/
@Override
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = -1;
while (!Thread.interrupted())
if (in.available() > 0) {
c = in.read();
break;
} else
Thread.yield();
if (c == -1) {
return -1;
}
b[off] = (byte) c;
int i = 1;
try {
for (; i < len; i++) {
c = -1;
if (in.available() > 0)
c = in.read();
if (c == -1) {
break;
}
b[off + i] = (byte) c;
}
} catch (IOException ee) {
}
return i;
}
@Override
public int available() throws IOException {
return in.available();
}
@Override
public void close() throws IOException {
in.close();
}
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
in.reset();
}
@Override
public boolean markSupported() {
return in.markSupported();
}
}
调整Thread.yield()
使其进入睡眠状态,直到可以接受的最大延迟时间为止,并为中断时的某些异常做好准备,但除此之外,它应该可以正常工作.
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.
这篇关于如何中断System.in上的读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!