PipedReader从未在流结束时准备好()

时间:2014-05-02 02:28:15

标签: java io nonblocking ready

我尝试编写以非阻塞方式从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;
    }
}

1 个答案:

答案 0 :(得分:1)

  

PipedReader从未在流的末尾准备好()

我同意。这不是它的用途。 ready()告诉您是否可以读取数据,而不是文件结束条件。见Javadoc:'如果循环缓冲区不为空,则准备好管道字符流。

没有办法做你正在尝试做的事情。 Streams和Readers是无可挽回的阻塞。您的代码基本上只是一种自行实现阻止的复杂方法,增加了延迟并增加了错误。这毫无意义。

我还会质疑你对管道读者和作家的使用。它们是非常无用的东西,实际上只是wait()notify().的概念验证可能你真正想要的是Queue.