简体   繁体   English

如何从标准输入读取非阻塞?

[英]how to read from standard input non-blocking?

    long end=System.currentTimeMillis()+60*10;
    InputStreamReader fileInputStream=new InputStreamReader(System.in);
    BufferedReader bufferedReader=new BufferedReader(fileInputStream);
    try
    {
        while((System.currentTimeMillis()<end) && (bufferedReader.readLine()!=null))
        {

        }
        bufferedReader.close();
    }
    catch(java.io.IOException e)
    {
        e.printStackTrace();
    }

I actually tried doing the above for reading in 600 miliseconds time after which it should not allow reading but the readline of the bufferedreader is blocking.Please help 我实际上尝试在600毫秒的时间内完成上述操作,之后它不应该允许读取,但缓冲读取器的读取线是阻塞的。请帮助

Using BufferedReader.available() as suggested by Sibbo isn't reliable. 使用Sibbo建议的BufferedReader.available()是不可靠的。 Documentation of available() states: available()状态的文档:

Returns an estimate of the number of bytes that can be read... It is never correct to use the return value of this method to allocate a buffer. 返回可以读取的字节数的估计值 ...使用此方法的返回值来分配缓冲区永远不正确。

In other words, you cannot rely on this value, eg, it can return 0 even if some characters are actually available. 换句话说,您不能依赖此值,例如,即使某些字符实际可用,它也可以返回0

I did some research and unless you are able to close the process input stream from outside, you need to resort to an asynchronous read from a different thread. 我做了一些研究,除非你能够从外部关闭进程输入流,否则你需要求助于来自不同线程的异步读取。 You can find an example how to read without blocking line by line here . 您可以在此处找到如何在不逐行阻止的情况下阅读的示例。


Update: Here is a simplified version of the code from the link above: 更新:以下是上述链接的简化版代码:

public class NonblockingBufferedReader {
    private final BlockingQueue<String> lines = new LinkedBlockingQueue<String>();
    private volatile boolean closed = false;
    private Thread backgroundReaderThread = null;

    public NonblockingBufferedReader(final BufferedReader bufferedReader) {
        backgroundReaderThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        String line = bufferedReader.readLine();
                        if (line == null) {
                            break;
                        }
                        lines.add(line);
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    closed = true;
                }
            }
        });
        backgroundReaderThread.setDaemon(true);
        backgroundReaderThread.start();
    }

    public String readLine() throws IOException {
        try {
            return closed && lines.isEmpty() ? null : lines.poll(500L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new IOException("The BackgroundReaderThread was interrupted!", e);
        }
    }

    public void close() {
        if (backgroundReaderThread != null) {
            backgroundReaderThread.interrupt();
            backgroundReaderThread = null;
        }
    }
}

You could check with BufferedReader.available() > 0 if there are chars to read. 如果有要读取的字符,您可以使用BufferedReader.available()> 0进行检查。

String s;

while((System.currentTimeMillis()<end))
{
    if (bufferedReader.available() > 0)
        s += bufferedReader.readLine();
}

bufferedReader.close();
long end=System.currentTimeMillis()+60*10;
InputStreamReader fileInputStream = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(fileInputStream);
try {
    while ((System.currentTimeMillis() < end)) {
        if (bufferedReader.ready()) {
            System.out.println(bufferedReader.readLine());
        }
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (bufferedReader != null) {
            bufferedReader.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The only reliable way would be to start a worker thread and do the actual reading inside it, while the caller thread would monitor the latency. 唯一可靠的方法是启动一个工作线程并在其中进行实际读取,而调用程序线程将监视延迟。

If the worker thread is waiting longer that allowed, the master thread would terminate it and throw an exception. 如果工作线程等待的时间超过允许的时间,主线程将终止它并抛出异常。

BufferReader.readLine() can block for a very long time if a line is extremely long like 1M chars. 如果一行非常长,就像1M字符一样,BufferReader.readLine()可以阻塞很长时间。

Does your file contains such long lines? 你的文件包含这么长的行吗?

If yes, you may have to break up the lines, or use per-char read methods like BufferReader.read(). 如果是,您可能必须分解行,或使用像BufferReader.read()这样的per-char读取方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM