PrintWriter ожидает сброса () - PullRequest
       16

PrintWriter ожидает сброса ()

3 голосов
/ 21 февраля 2011

Я пишу многопоточный сокет-сервер.Я использую nio ServerSocketChannel для принятия соединений.Затем я читаю и пишу (в отдельных потоках) на socketChannel, используя bufferedreader, и пишу писателю.Проблема в том, что PrintWriter блокирует и ждет команду flush().Он блокирует поток до тех пор, пока BufferedReader не получит данные.

Ответы [ 2 ]

2 голосов
/ 21 февраля 2011

Это означает, что приемник медленно читает. Вот как работает блокировка ввода / вывода. Если вы хотите неблокировать ввод-вывод, вы уже на этом пути, так как вы уже используете NIO. Хотя я действительно не вижу смысла использовать NIO в режиме блокировки вообще.

0 голосов
/ 21 февраля 2011

Как говорит @EJP, именно так работает блокировка ввода-вывода.Действительно, эта проблема присуща любой архитектуре, где у вас есть производитель и потребитель.Если производитель производит материал (в данном случае строки текстового вывода) быстрее, чем потребитель может его потреблять, то в конечном итоге производитель должен блокировать.


Как вы можете решить эту проблему?Сначала некоторые общие вещи.

Если производитель производит вещи быстрее, чем потребитель потребляет их в долгосрочной перспективе , вы находитесь между молотом и наковальней.Вы должны либо уменьшить скорость производства производителя, ускорить скорость потребления потребителя, либо уменьшить накладные расходы в конвейере до того же эффекта.Ничто другое не работает.

Если несоответствие скорости является только временным, вы можете «замаскировать трещины», добавив некоторую дополнительную буферизацию в конвейер.Если соединение между ними имеет некоторую возможность буферизации, вы можете увеличить его.Кроме того, вы можете добавить дополнительную буферизацию на стороне производителя или потребителя.


Вот некоторые вещи, которые могут помочь в вашем конкретном случае.

  • Уменьшите суммуматериала, который вы пишете в темах продюсера.

  • Делайте меньше работы в потоках потребителя или профилируйте / настраивайте их, чтобы выполнять работу быстрее.

  • Не используйте сокет для связи между двумя потоками в одной JVM.Если вы можете организовать это, используйте пару Java PipeInputStream / PipeOutputStream или сверните свой собственный эквивалент.(Если вы используете сокет, для чтения и записи требуются системные вызовы, копирование данных в буферы ядра и из них и т. Д.)

  • В случае, когда связь должна выйдите за пределы JVM, убедитесь, что вы используете Buffered* оболочки для базовых потоков, чтобы уменьшить количество системных вызовов, выполняемых во время чтения / записи.

...