我尝试编写以非阻塞方式从Reader
读取的代码,即在确保read()
返回ready()
后仅调用true
。
要测试代码,我使用PipedReader
/ PipedWriter
组合,ready()
效果很好,直到我关闭PipedWriter
,这也标志着结束在PipedReader
一边流。但是,虽然ready()
方法永远不会再次返回true
,但read()
会在调用时立即返回-1
。
在这种情况下,是否有非阻塞方式来确定对read()
的调用不会阻止?
这是一个重现问题的例子。
package test;
import java.io.*;
public class Piper
{
public static void main(String[] args) throws Exception
{
int sleepBetweenChars = 100;
boolean throttle = true;
Reader reader = new StringReader("abc");
if (throttle)
reader = throttle(sleepBetweenChars, reader);
while (true)
{
if (reader.ready())
{
int c = reader.read();
System.out.println("Read " + c);
if (c == -1)
break;
}
else
{
System.out.println("Not ready");
Thread.sleep(sleepBetweenChars);
if (!reader.ready())
{
System.out.println("Still not ready, sleep some more");
Thread.sleep(20 * sleepBetweenChars);
if (!reader.ready())
{
int c = reader.read();
System.out.println("Still not ready, we read nonetheless: " + c);
if (c == -1)
break;
}
}
}
}
}
private static Reader throttle(final int sleepBetweenChars, final Reader in) throws IOException
{
final PipedWriter pw = new PipedWriter();
PipedReader pr = new PipedReader(pw);
(new Thread(new Runnable()
{
public void run()
{
System.out.println("Start piping");
int c;
try
{
while ((c = in.read()) != -1)
{
pw.write(c);
Thread.sleep(sleepBetweenChars);
}
pw.close();
System.out.println("Closed PipedWriter");
}
catch (Throwable t)
{
t.printStackTrace();
}
}
})).start();
return pr;
}
}
答案 0 :(得分:1)
PipedReader从未在流的末尾准备好()
我同意。这不是它的用途。 ready()
告诉您是否可以读取数据,而不是文件结束条件。见Javadoc:'如果循环缓冲区不为空,则准备好管道字符流。
没有办法做你正在尝试做的事情。 Streams和Readers是无可挽回的阻塞。您的代码基本上只是一种自行实现阻止的复杂方法,增加了延迟并增加了错误。这毫无意义。
我还会质疑你对管道读者和作家的使用。它们是非常无用的东西,实际上只是wait()
和notify().
的概念验证可能你真正想要的是Queue.