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
被通知。
我不确定如何运行你的代码,所以我无法深入了解它。 希望这可以帮助。
我实现了一些类似的东西,并问了一个问题是否有其他人有更好的思考和测试代码。