Java 如何停止等待System.in的线路?

Java 如何停止等待System.in的线路?,java,io,Java,Io,我有一个从标准输入执行读取的服务。给你 public class ReaderService{ private BufferedReader reader; private volatile boolean closed; public void start(){ while(!closed){ reader = new BufferedReader(new InputStreamReader(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
    方法中的
    reader
    重命名为
    service
  • 在终端中运行程序
  • 当程序正在等待您按Enter键时,在另一个终端中:
    jps-v
    ——找到运行
    ReaderService
    的JVM进程(p),然后执行
    jstack
    。这将为您带来一个Java线程转储
  • 您应该得到类似的结果(为了简洁起见,省略了其他线程):

    如果您这样做,您还会看到一些有趣的行为:

  • 在Unix终端上,创建一个包含一些文本的文本文件
    x
  • 运行java ReaderService
    也许这种行为更接近你的期望。但是它与I/O缓冲如何为各种类型的流工作有关。

    如果主线程对最终试图关闭的流具有独占访问权,那么您的期望是正确的。但事实并非如此,这就是为什么这个程序演示了等待。当您按enter键时(当行缓冲流如
    System.in
    刷新内容时),程序将按预期退出

    要进行说明,请执行以下操作:

  • main
    方法中的
    reader
    重命名为
    service
  • 在终端中运行程序
  • 当程序正在等待您按Enter键时,在另一个终端中:
    jps-v
    ——找到运行
    ReaderService
    的JVM进程(p),然后执行
    jstack
    。这将为您带来一个Java线程转储
  • 您应该得到类似的结果(为了简洁起见,省略了其他线程):

    如果您这样做,您还会看到一些有趣的行为:

  • 在Unix终端上,创建一个包含一些文本的文本文件
    x
  • 运行java ReaderService 也许这种行为更接近你的期望。但它与各种类型的流的I/O缓冲工作方式有关。

    在读取之前检查reader.ready()。如果为false,则检查closed(关闭)标志并睡眠100毫秒左右

    这并不理想,但我认为这是在System.in上超时的最佳方式。不过,这只适用于System.in——如果您正在为套接字提供服务,则应该使用真正的超时。

    在读取之前检查reader.ready()。如果为false,则检查closed(关闭)标志并睡眠100毫秒左右


    这并不理想,但我认为这是在System.in上超时的最佳方式。不过,这只适用于System.in——如果您正在为套接字提供服务,那么您应该使用真正的超时。

    可能会有所帮助:@acdcjunior有趣,所以只需定期检查是否有数据来完成readLine是唯一的方法?当您希望线程
    中断时,
    可能会有所帮助:@acdcjunior有趣,所以,只要定期检查我们是否有数据来完成readLine是唯一的方法?当您希望线程中断时
    "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)
    
    public void close() throws IOException {
        synchronized (lock) {
            if (in == null)
                return;
            try {
                in.close();
            } finally {
                in = null;
                cb = null;
            }
        }
    }