как выбрать java nio против io?

Как мы знали, если мы хотим использовать традиционный ввод-вывод для создания сервера, он должен где-то блокироваться, поэтому нам пришлось использовать режим цикла или одного потока с одним сокетом, поэтому nio кажется лучшим выбором. Итак, я хочу знать, является ли nio лучшим выбором навсегда?


person jiafu    schedule 15.10.2012    source источник
comment
Вы имеете в виду новый IO (до Java 7) или новый модный неблокирующий IO с ребрендингом (docs.oracle.com/javase/7/docs/technotes/guides/io/)?   -  person RNJ    schedule 15.10.2012


Ответы (7)


ИМХО, блокировка ввода-вывода, как правило, является самой простой в использовании, и если у вас нет особых требований, требующих большего от вашей системы, вам следует придерживаться самого простого варианта.

Следующий простейший вариант — блокировка NIO, который я часто предпочитаю, если хочу чего-то более эффективного или контролируемого, чем IO. Он по-прежнему относительно прост, но позволяет использовать ByteBuffers. например ByteBuffers поддерживает прямой порядок следования байтов.

Распространенным вариантом является использование неблокирующего NIO с селекторами. Большая часть сложности, которую это вносит, может быть решена такими фреймворками, как Netty или Mina. Я предлагаю вам использовать такую ​​библиотеку, если вам нужен неблокирующий ввод-вывод, например. потому что у вас есть тысячи одновременных подключений к серверу. ИМХО У вас тысячи подключений, вам следует подумать о том, чтобы иметь больше серверов, если только то, что делает каждое подключение, не является довольно тривиальным. Насколько я знаю, Google использует больше серверов, а не тысячи пользователей на сервер.

Более экстремальный вариант — использовать NIO2. Это еще более сложно и долго писать, чем неблокирующий NIO. Я не знаю никаких фреймворков, которые хорошо это поддерживают. то есть это на самом деле быстрее, когда вы это делаете. AFAIK Похоже, это стоит использовать, если у вас есть Infiniband (для чего он и был разработан), но, возможно, не стоит использовать, если у вас есть Ethernet.

person Peter Lawrey    schedule 15.10.2012
comment
Спасибо за ваш пост. Я наткнулся на ваш ответ, так как исследую ту же тему. Я пытаюсь понять улучшения ОС, которые nio и nio2 предоставляют java-программистам. Пара из них - DMA и файлы с отображением памяти. Сталкивались ли вы с такими улучшениями? - person Andy Dufresne; 18.03.2013
comment
Должен ли я рассматривать использование NIO вместо IO в случае чтения потока с 1000 сообщений за 1 секунду? - person Maroun; 22.04.2015
comment
@MarounMaroun это зависит от размера сообщений, но я предлагаю использовать некоторую буферизацию, и вы сможете обрабатывать сотни тысяч сообщений в секунду, независимо от того, какой другой выбор вы сделаете. Примечание: по возможности старайтесь, чтобы сообщения были меньше. - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey большое спасибо. У меня открыт поток из Твиттера, я должен читать 1000 сообщений в секунду, но почему-то получаю ошибку о том, что их буфер достиг предела. Говоря об использовании некоторой буферизации, вы имеете в виду буферы ввода-вывода? - person Maroun; 22.04.2015
comment
@MarounMaroun в этом случае да. Какого предела вы достигли? Возможно ли, что вы читаете сообщение, которое не является полным. Поток байтов понимает не только сообщения, а только байты, поэтому при чтении из потока вы можете получить любую часть сообщения, даже по одному байту за раз. Как вы с этим справляетесь? - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey Я просто читаю BufferedReader#readLine (поскольку обещано, что я получаю каждый JSON в виде строки, и это работает - я действительно вижу, что читаю полные JSON на каждой итерации). Ограничение взято из твиттера: Принудительно закрыть соединение с **.*.**.**, так как достигнуто максимально допустимое количество резервных копий (размер буфера составляет 311298 сообщений) (если нужна помощь, комментарии беспокоят вас, дайте мне знать :)) - person Maroun; 22.04.2015
comment
@MarounMaroun это означает, что твиттер отправлял вам данные быстрее, чем вы их читаете. Я предлагаю, чтобы после того, как вы прочитали строку, вы ничего не делали в этом потоке, кроме как добавляли его в BlockingQueue. Скорее всего ваша программа для разбора и обработки сообщений работала слишком медленно. - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey большое спасибо, попробую. Последний вопрос: уместно ли увеличить размер буфера (сейчас я использую значение по умолчанию) и, скажем, установить его примерно на 1 МБ? - person Maroun; 22.04.2015
comment
@MarounMaroun, вы можете сделать это, но очередь стоит у нас, чтобы вы могли видеть, что отстаете, и, возможно, принять меры по исправлению положения. Если вы не в состоянии идти в ногу в долгосрочной перспективе, дополнительная буферизация и даже очередь сами по себе не помогут. Буферизация поможет, если у вас случаются всплески активности, и вы не можете поддерживать ее в течение короткого периода времени, но можете в долгосрочной перспективе. Сглаживает всплески активности. - person Peter Lawrey; 22.04.2015
comment
Небольшое обновление @PeterLawrey, возможно, поможет другим посетителям ... отчасти проблема заключалась в самой машине (мое приложение было развернуто на машине AWS t2.small, которая не обеспечивала хорошей сетевой производительности, после того как я переместил приложение на более продвинутую машину, количество ошибок значительно уменьшилось. - person Maroun; 26.04.2015

Если вам нужен неблокирующий ввод-вывод, NIO не лучший выбор, это единственный выбор в Java. Имейте в виду, что люди по-прежнему регулярно используют старый IO, потому что с ним намного проще кодировать. NIO API довольно сырой и представляет собой скорее низкоуровневую технологию, чем API на стороне клиента. Я предлагаю использовать NIO через API, который предоставляет более простой интерфейс для задач, которые вы хотите решить с помощью неблокирующего ввода-вывода.

person Marko Topolnik    schedule 15.10.2012
comment
Итак, если я вызову Files.exit(/path/to/nfs/file), а файл NFS устарел из-за некоторых проблем с монтированием nfs, вызов не заблокируется, не так ли? - person AsadSMalik; 21.11.2018

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

 1. if(Files.notExists(path)) { } 
 2. Files.createDirectory(path);
 3. Files.newInputStream(path) targetPath.resolve("somefile.txt");
 4. Files.newBufferedWriter(path, charset);
 5. DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);

и он отлично работает для меня. Я предпочитаю Path вместо старого File из-за таких методов, как relativize или resolveSibling.

Не кажется мне более сложным, чем IO.

person user3629892    schedule 05.05.2015
comment
Тем не менее, это блокирует - person Alejandro Navas; 19.02.2021

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

Чтобы придать моему ответу некоторый вес, я только что провел три месяца, поддерживая и исправляя ошибки уровня интеграции, где использовался необработанный Java NIO (т.е. не использовалась всеобъемлющая структура). Дизайн был основан, по сути, на клиентских потоках, добавляющих сообщения в очередь, и небольшом количестве рабочих потоков, выполняющих свою магию NIO, а затем передающих ответы обратно клиентским потокам в зависимости от событий. Оглядываясь назад, я не могу оправдать первоначальное решение использовать NIO, так как это стало отвлечением, которое съело значительное количество времени, которое должно было быть потрачено на бизнес-логику более высокого уровня.

person Nico de Wet    schedule 24.09.2013

Вы можете использовать любой из них, если только вы не собираетесь создавать «супербыстрый» сервер.

Конечно, хорошим подходом здесь является использование nio, так как это новый и современный способ написания многоклиентских серверов для задач с высокой пропускной способностью.

person Max    schedule 15.10.2012
comment
Сомнительный. Есть много исследований, которые говорят об обратном. Новизна не всегда является улучшением. - person user207421; 15.10.2012
comment
@EJP согласился - некоторые из моих тестов с NIO на самом деле были медленнее! - person RNJ; 15.10.2012
comment
@EJP Конечно, вы абсолютно правы, но здесь нет никаких сомнений. Если автор собирается реализовать сервер для своих нужд, который не собирается обслуживать более 100 клиентов, то нет необходимости использовать nio. Старая школа просто проще в использовании и понимании, чем неблокирующая асинхронная модель. - person Max; 15.10.2012
comment
@MyNameIsTooCommon Это ничего не значит. Другой вопрос, если вы используете nio для соответствующих задач. - person Max; 15.10.2012
comment
@Max Если я прав, я не понимаю всего после «но». - person user207421; 17.10.2012

Некоторые преимущества API NIO.2 по сравнению с устаревшим классом java.io.File для работы с файлами:

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

Конкретные варианты использования и дополнительные сведения см. в этом статья

person Imar    schedule 26.09.2018

Традиционный ввод-вывод — это простой и упрощенный код, NIO — более сложный, но и более гибкий. В моем случае я предпочитаю использовать IO для маленьких потоков и NIO для больших потоков, но nio действительно сложнее

с NIO мне нужно создать целый пакет для управления им вместо пакета io, который я напрямую использую snippet

person Andrea Bori    schedule 04.11.2014
comment
Я не согласен. Смотрите это: Files.readAllLines(Paths.get(filename), Charset.forName("UTF-8"));. В одной строке вы проанализировали файл и поместили все в список; это было бы классным упражнением в старом IO. - person Evil Washing Machine; 07.04.2016
comment
ну, @EvilWashingMachine, я думаю, ты прав :) но .. если мы говорим о разборе файла и извлечении информации, в любом случае с твоим методом ты будешь выполнять упражнение длиной в класс в старом вводе-выводе ^^ - person Andrea Bori; 09.04.2016