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

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(); } 

我实际上尝试在600毫秒的时间内完成上述操作,之后它不应该允许读取但是bufferedreader的readline是阻塞的。请帮助

如果有要读取的字符,您可以使用BufferedReader.available()> 0进行检查。

 String s; while((System.currentTimeMillis() 0) s += bufferedReader.readLine(); } bufferedReader.close(); 

使用Sibbo建议的BufferedReader.available()是不可靠的。 available()状态的文档:

返回可读取的字节数的估计值 …使用此方法的返回值来分配缓冲区永远不正确。

换句话说,您不能依赖此值,例如,即使某些字符实际可用,它也可以返回0

我做了一些研究,除非你能够从外部关闭进程输入流,否则你需要求助于来自不同线程的异步读取。 您可以在此处找到如何在不逐行阻止的情况下阅读的示例。


更新:以下是上述链接的简化版代码:

 public class NonblockingBufferedReader { private final BlockingQueue lines = new LinkedBlockingQueue(); 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; } } } 
 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(); } } 

如果一行非常长,就像1M字符一样,BufferReader.readLine()可以阻塞很长时间。

你的文件包含这么长的行吗?

如果是,您可能必须拆分行,或使用像BufferReader.read()这样的per-char读取方法。

唯一可靠的方法是启动一个工作线程并在其中进行实际读取,而调用者线程将监视延迟。

如果工作线程等待的时间超过允许的范围,则主线程将终止它并抛出exception。