【问题标题】:Better alternative for PipedReader/PipedWriter?PipedReader/PipedWriter 的更好选择?
【发布时间】:2011-02-20 01:48:58
【问题描述】:

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

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

【问题讨论】:

  • 这可能不是你想要的,但是你的写线程能在写完东西后通知读线程吗?并且阅读线程会在ready() 为真时继续阅读,然后在不为真时休眠?
  • 您能告诉我们您的代码吗? wait(1000) 不应该是问题,因为作者在写东西时会通知读者。然后读者从他的 wait() 中逃脱。
  • 谢谢,菲尔。我现在不在家,所以我无法测试它,但根据源代码 PipedWriter.flush() 似乎可以通知读者。我今天晚些时候试试。

标签: java data-structures


【解决方案1】:

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

解决方案是在向管道写入内容后始终调用PipedWriter.flush()。 flush 所做的只是在阅读器上调用notifyAll()。修复有问题的代码looks like this

(对我来说,PipedReader/PipedWriter 实现看起来非常像过早优化的情况 - 为什么不在每次写入时通知All?读者也在活动循环中等待,每秒醒来,而不是仅在有可以阅读的东西。代码还包含一些 todo cmets,它所做的读取器/写入器线程检测不够复杂。)

PipedOutputStream 中似乎也存在同样的问题。在我当前的项目中手动调用flush() 是不可能的(不能修改Commons IO 的IOUtils.copy()),所以我通过为管道类创建low-latency wrappers 来修复它。他们的工作比原来的课程好得多。 :-)

【讨论】:

    【解决方案2】:

    BlockingQueue 周围封装一个字符流API 应该相当容易。

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

    【讨论】:

    • 我想你的意思是链接到“java.sun.com/javase/6/docs/api/java/util/concurrent/…
    • 是的,这是我的 B 计划,如果我找不到一个已经满足我需要的课程。
    • 谢谢菲尔。我的谷歌搜索太快了。 :-)
    • 确实很反常。我在测试中发现了延迟,分析了原因在 PipedReader 中,并发现原因是 java2s.com/Open-Source/Java-Document/6.0-JDK-Core/io-nio/java/… 中硬编码的 wait(1000) 调用 - 这不是第一次出现一些旧的(自 JDK1.1 起) Java 标准库的代码很丑。
    • 只是为了向读者澄清:wait(1000) 不像sleep(1000) - 当它是notifyed 时,它会立即退出数据可用。超时是为了处理错误情况——特别是如果数据源线程意外死亡并且无法再通知。
    【解决方案3】:

    @Esko Luontola,我一直在阅读您在 sbt 包中的代码,试图了解您在做什么。似乎您想启动 Process 并将输入传递给它,并将操作的结果发送到不同的地方。这完全正确吗?

    我会尝试修改ReaderToWriterCopier 中的主循环,以便代替执行read() - 显然当涉及PipedReader 时会导致轮询的阻塞操作 - 您明确等待Writer 到@987654327 @。文档清楚地表明flush 会导致任何Readers 得到通知。

    我不确定如何运行您的代码,因此无法深入了解它。希望这会有所帮助。

    【讨论】:

    • 我的用例是Process 打印的内容有多个阅读器,每个阅读器都需要自己的流副本,从当前时刻开始到阅读器关闭时结束.不同的读者要互不影响。例如,读取 PipedReader 的人是OutputReader.waitForOutput()。作者是ReaderToWriterCopier。主程序是SbtRunner,测试源有SbtRunnerTester使用它。 SBT 代表code.google.com/p/simple-build-tool
    【解决方案4】:

    我实现了一些类似的东西,asked a question 是否有其他人有更好的想法和测试代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多