我需要一个缓冲的char
流,我在一个线程中编写,我从另一个线程中读取。 Right now我正在使用PipedReader和PipedWriter,但这些类会导致性能问题:当内部缓冲区为空时,PipedReader会执行wait(1000)
,这会导致我的应用程序明显滞后。
是否会有一些库与PipedReader / PipedWriter做同样的事情,但性能更好?或者我是否必须实施自己的车轮?
答案 0 :(得分:6)
问题在于,当某些内容被写入PipedWriter时,它不会自动通知PipedReader有一些数据需要读取。当一个人试图读取PipedReader并且缓冲区为空时,PipedReader将循环并等待wait(1000)
调用,直到缓冲区有一些数据。
解决方案是在向管道写入内容后始终调用PipedWriter.flush()
。刷新所做的就是在阅读器上调用notifyAll()
。有问题的代码looks like this的修复程序。
(对我而言,PipedReader / PipedWriter实现看起来非常类似于过早优化的情况 - 为什么不在每次写入时都通知?还有读者在一个活动循环中等待,每秒唤醒,而不是仅在有时才唤醒需要阅读的东西。代码还包含一些todo注释,它所做的读/写线程检测不够复杂。)
同样的问题似乎也出现在PipedOutputStream中。在我当前的项目中,手动调用flush()
是不可能的(不能修改Commons IO的IOUtils.copy()),所以我通过为管道类创建low-latency wrappers来修复它。他们的工作比原来的课程要好得多。 : - )
答案 1 :(得分:1)
在BlockingQueue
周围包装char流API应该相当容易。
但是,我必须说,PipedReader
使用轮询等待数据似乎很不正常。这是在某处记录的,还是以某种方式为自己发现了?
答案 2 :(得分:1)
@Esko Luontola,我一直在阅读sbt包中的代码,试图了解你在做什么。您似乎想要启动Process
并将输入传递给它,并将操作的结果转到不同的位置。这完全正确吗?
我会尝试修改ReaderToWriterCopier
中的主循环,这样就不会执行read()
- 一个阻塞操作显然在涉及PipedReader
时导致轮询 - 你明确地等待Writer
到flush
。文档清楚明确flush
会导致通知任何Reader
。
我不确定如何运行您的代码,因此我无法深入了解它。希望这会有所帮助。
答案 3 :(得分:0)
我实现了一些类似的东西,asked a question是否有其他人有更好的思考和测试代码。