[英]How to stop waiting for line from System.in?
我有一项从标准输入执行读取的服务。 这里是
public class ReaderService{
private BufferedReader reader;
private volatile boolean closed;
public void start(){
while(!closed){
reader = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("IOException");
}
}
}
public void stop(){
try {
reader.close();
} catch (IOException e) {
System.exit(1);
}
closed = true;
}
}
我使用它如下:
public static void main(String[] args) throws InterruptedException{
Thread t = new Thread(new Runnable() {
public void run() {
reader.start();
}
});
t.start();
Thread.sleep(5000);
reader.stop();
}
问题是调用ReaderService::stop()
不会中断下一行的唤醒。 我以为会抛出IOExecption
。
有没有办法从另一个线程“中断”这样的服务? 也许BufferedReader
在这里不是一个很好的选择...
如果主线程对它最终试图关闭的流具有独占访问权,那么您的期望是正确的。 但这不是事实,这就是该程序演示等待的原因。 当您按Enter键(这是行缓冲流,例如System.in
刷新内容)时,程序将按预期方式退出。
为了说明,请执行以下操作:
main
service
reader
方法。 Enter
,在另一个终端上: jps -v
ReaderService
查找运行ReaderService
的JVM进程(p),然后执行jstack <p>
。 这为您带来了Java线程转储 。 您应该得到类似的内容(为简洁起见,省略了其他线程):
"main" #1 prio=5 os_prio=31 tid=0x00007fef4d803000 nid=0xf07
waiting for monitor entry [0x000000010b7a3000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.io.BufferedReader.close(BufferedReader.java:522)
- waiting to lock <0x000000076ac47f78> (a java.io.InputStreamReader)
at ReaderService.stop(ReaderService.java:19)
at ReaderService.main(ReaderService.java:34)
"Thread-0" #10 prio=5 os_prio=31 tid=0x00007fef4c873800 nid=0x5503 runnable [0x000000012b497000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:255)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
- locked <0x000000076ab1bf10> (a java.io.BufferedInputStream)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x000000076ac47f78> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x000000076ac47f78> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at ReaderService.start(ReaderService.java:10)
at ReaderService$1.run(ReaderService.java:29)
at java.lang.Thread.run(Thread.java:745)
如您所见,在main
线程完成睡眠之后,它进入BLOCKED
状态,等待获取表示可变共享状态(在这种情况下, main
线程与线程t
共享)的BufferedReader
上的锁。 如预期的那样,线程t
已经锁定了BufferedReader
的锁0x000000076ac47f78
并进入了临界区。 请注意, t
处于RUNNABLE
状态,仅等待有人按下Enter
。 一旦发生这种情况,事情就应该恢复正常,因为最终, main
线程应该像BufferedReader.java
源代码中一样(在JDK 1.8中的第522行附近)成功获取锁:
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
如果您这样做,还将看到一些有趣的行为:
x
,其中包含一些文本。 java ReaderService < x
。 也许这种行为更接近您的期望。 但是,这与各种流类型的I / O缓冲的工作方式有关。
阅读前检查reader.ready()。 如果为假,则检查关闭标志并睡眠100毫秒左右。
这并不理想,但是我认为这是在System.in上超时的最佳方法。 不过,这仅适用于System.in -如果您正在使用套接字,则应使用实时超时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.