Лучшая альтернатива для PipedReader / PipedWriter? - PullRequest
7 голосов
/ 16 мая 2010

Мне нужен буферизованный поток char, в который я пишу в одном потоке и из которого читаю в другом. Прямо сейчас Я использую PipedReader и PipedWriter , но эти классы вызывают проблему производительности: PipedReader выполняет wait(1000), когда его внутренний буфер пуст , что заставляет мое приложение заметно отставать.

Будет ли какая-нибудь библиотека, которая делает то же самое, что и PipedReader / PipedWriter, но с лучшей производительностью? Или мне придется внедрить свои собственные колеса?

Ответы [ 4 ]

6 голосов
/ 16 мая 2010

Проблема заключалась в том, что когда что-то записывается в PipedWriter, оно автоматически не уведомляет PipedReader о наличии данных для чтения. Когда кто-то пытается прочитать PipedReader и буфер пуст, PipedReader будет зацикливаться и ждать, используя вызов wait(1000), пока в буфере не будет данных.

Решение состоит в том, чтобы вызывать PipedWriter.flush() всегда после записи чего-либо в канал. Все, что делает флеш, это вызывает notifyAll() на ридере. Исправление к рассматриваемому коду выглядит следующим образом .

(Для меня реализация PipedReader / PipedWriter очень похожа на случай преждевременной оптимизации - почему бы не уведомлять все при каждой записи? Читатели также ждут в активном цикле, просыпаясь каждую секунду, вместо пробуждения только при наличии что-то для чтения. В коде также есть некоторые комментарии к задачам о том, что обнаружение потоков чтения / записи, которое он делает, недостаточно развито.)

Похоже, эта проблема также присутствует в PipedOutputStream . В моем текущем проекте вызов flush() вручную невозможен (невозможно изменить IOUtils.copy () Commons IO), поэтому я исправил это, создав оболочки с низкой задержкой для труба классов. Они работают намного лучше, чем оригинальные классы. : -)

1 голос
/ 16 мая 2010

@ Эско Луонтола, я читал твой код в пакете sbt, чтобы понять, что ты делаешь. Похоже, что вы хотите запустить Process и передать входные данные, и результат действия будет передан в разные места. Это вообще правильно?

Я бы попытался изменить основной цикл в ReaderToWriterCopier, чтобы вместо выполнения read() - операции блокировки, которая, очевидно, когда задействован PipedReader, вызывает опрос - вы явно ждете, когда Writer - flush. Из документации ясно, что flush заставляет уведомлять любые Reader s.

Я не уверен, как запустить ваш код, чтобы я не мог углубиться в него. Надеюсь, это поможет.

1 голос
/ 16 мая 2010

Должно быть достаточно легко обернуть API потока символов вокруг BlockingQueue.

Я должен сказать, однако, кажется довольно странным, что PipedReader будет использовать опрос для ожидания данных. Это где-то задокументировано, или вы как-то обнаружили это для себя?

0 голосов
/ 16 мая 2010

Я реализовал что-то похожее и задал вопрос есть ли у кого-нибудь лучше продуманный и протестированный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...