如何中断System.in上的读取? [英] How to interrupt reading on System.in?

查看:184
本文介绍了如何中断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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆