如果我开始阅读System.in
,它会阻塞线程直到获取数据。没有办法阻止它。以下是我尝试过的所有方法:
- 中断线程
- 停止线程
- Closing
System.in
- Calling
System.exit(0)
确实停止了线程,但它也杀死了我的应用程序,所以不理想。
- 在控制台中输入一个字符会使该方法返回,但我不能依赖用户输入。
不起作用的示例代码:
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
并永远奔跑。
我如何阅读System.in
以可中断的方式?
您应该设计 run 方法,以便它可以自行确定何时终止。在线程上调用 stop() 或类似方法将是本质上不安全.
然而,仍然存在一个问题:如何避免 System.in.read 内部阻塞?为此,您可以在读取之前轮询 System.in.available 直到它返回 > 0。
示例代码:
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();
}
});
当然,通常认为使用阻塞IO方法比轮询更有利。但民意调查确实有其用处。在您的情况下,它允许该线程干净地退出。
更好的方法:
A 更好的方法避免轮询的方法是重构代码,以便您打算杀死的任何线程都不允许直接访问System.in
。这是因为 System.in 是一个不应该关闭的 InputStream。相反,主线程或另一个专用线程将从 System.in 读取(阻塞),然后将任何内容写入缓冲区。反过来,该缓冲区将由您想要杀死的线程监视。
示例代码:
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
}
可是等等! (另一个 Java API 失败)
不幸的是,正如用户指出的Motowski,Java API 实现中存在“Won't Fix”错误PipedInputSteam
。因此,如果您使用未修改的库版本PipedInputSteam
如上所示,它有时会通过以下方式触发长时间睡眠wait(1000)
。要解决该错误,开发人员必须自己制作FastPipedInputStream
所描述的子类here.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)