Лучшая альтернатива для PipedReader/PipedWriter?

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

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

7
задан Esko Luontola 16 May 2010 в 11:37
поделиться

4 ответа

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

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

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

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

.
7
ответ дан 7 December 2019 в 03:12
поделиться

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

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

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

1
ответ дан 7 December 2019 в 03:12
поделиться

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

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

1
ответ дан 7 December 2019 в 03:12
поделиться

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

0
ответ дан 7 December 2019 в 03:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: