Проблема заключалась в том, что когда что-то записывается в PipedWriter, оно автоматически не уведомляет PipedReader о наличии данных для чтения. Когда кто-то пытается прочитать PipedReader и буфер пуст, PipedReader будет зацикливаться и ждать, используя вызов wait(1000)
, пока в буфере не будет данных.
Решение состоит в том, чтобы вызывать PipedWriter.flush()
всегда после записи чего-либо в канал. Все, что делает флеш, это вызывает notifyAll()
на ридере. Исправление к рассматриваемому коду выглядит следующим образом .
(Для меня реализация PipedReader / PipedWriter очень похожа на случай преждевременной оптимизации - почему бы не уведомлять все при каждой записи? Читатели также ждут в активном цикле, просыпаясь каждую секунду, вместо пробуждения только при наличии что-то для чтения. В коде также есть некоторые комментарии к задачам о том, что обнаружение потоков чтения / записи, которое он делает, недостаточно развито.)
Похоже, эта проблема также присутствует в PipedOutputStream . В моем текущем проекте вызов flush()
вручную невозможен (невозможно изменить IOUtils.copy () Commons IO), поэтому я исправил это, создав оболочки с низкой задержкой для труба классов. Они работают намного лучше, чем оригинальные классы. : -)