PipedReader / PipedWriter的更好选择?

我需要一个缓冲的char流,我在一个线程中写入,我从另一个线程中读取。 现在我正在使用PipedReader和PipedWriter ,但这些类会导致性能问题:当内部缓冲区为空时,PipedReader会执行wait(1000) ,这会导致应用程序明显滞后。

是否会有一些库与PipedReader / PipedWriter做同样的事情,但性能更好? 或者我必须实施自己的车轮?

问题是,当某些内容被写入PipedWriter时,它不会自动通知PipedReader有一些数据需要读取。 当一个人试图读取PipedReader并且缓冲区为空时,PipedReader将循环并等待使用wait(1000)调用,直到缓冲区有一些数据。

解决方案是在向管道写入内容之后始终调用PipedWriter.flush() 。 flush执行的所有操作都是在reader上调用notifyAll() 。 对相关代码的修复看起来像这样 。

(对我而言,PipedReader / PipedWriter实现看起来非常像过早优化的情况 – 为什么不在每次写入时都通知?还有读者在一个活动循环中等待,每秒唤醒,而不是只在有东西要读时才醒来该代码还包含一些todo注释,它所做的读写器线程检测不够复杂。)

同样的问题似乎也出现在PipedOutputStream中 。 在我当前的项目中,手动调用flush()是不可能的(不能修改Commons IO的IOUtils.copy() ),所以我通过为管道类创建低延迟包装器来修复它。 他们的工作比原来的课程要好得多。 🙂

BlockingQueue周围包装char流API应该相当容易。

但是,我必须说, PipedReader使用轮询等待数据似乎很不正常。 这是在某处记录的,还是以某种方式为自己发现了?

@Esko Luontola,我一直在阅读sbt包中的代码,试图了解你在做什么。 看起来你想要启动一个Process并将输入传递给它,并将操作的结果转到不同的地方。 这一切都正确吗?

我会尝试修改ReaderToWriterCopier的主循环,以便不执行read() – 一个阻塞操作,显然当涉及PipedReader时会导致轮询 – 您明确等待Writer flush 。 文档很清楚, flush会导致任何Reader被通知。

我不确定如何运行你的代码,所以我无法深入了解它。 希望这可以帮助。

我实现了一些类似的东西,并问了一个问题是否有其他人有更好的思考和测试代码。