Горячая вакансия – релокация в Берлин! Узнать подробности...
Горячая вакансия – релокация в Берлин! Узнать подробности...

Чем отличается блокирующее чтение от неблокирующего?

Посмотреть в Telegram: @JavaSobes/109
В контексте Java речь в этом вопросе идет о блокирующем/неблокирующем чтении из потоков данных.

Классы блокирующего чтения находятся в пакете java.io. Вы наверняка много раз сталкивались с ними, работая с файлами и консольным вводом-выводом (классы Reader, IOException, InputStream). При блокирующем чтении тред останавливается, пока не получит из потока необходимые данные. Для этих самых распространенных случаев использование неблокирующего чтения не несет пользы, потому что сама запись пользователем консоли и жестким диском будет последовательной.

Чтение данных из сетевого подключения – другое дело. Обычно программа обрабатывает данные быстрее, чем работает сеть. Возникают паузы, в которые поток блокирующего чтения стоит в ожидании, не принося пользы. К тому же серверное приложение работает со многими параллельными подключениями.

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

Для случаев, когда в вашем приложении ожидается большое количество подключений, был добавлен пакет стандартной библиотеки java.nio. С помощью NIO один тред может обслуживать несколько сетевых соединений одновременно, и переключаться между ними не теряя времени на ожидание данных.
IO использует потоки. данные приходят последовательно, и сами нигде не сохраняются. Если вы не обеспечили буферизацию вручную, нет возможности откатиться назад и прочитать уже пришедшие данные еще раз.

NIO сразу читает данные в буфер. Вы можете перемещаться по этому буферу перечитывая уже прочитанную ранее информацию. Плата за это – необходимость вручную следить, что буфер заполнен достаточным объемом данных для обработки, и что он не переполнился.

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

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