как да избера java nio срещу io?

Както знаехме, ако искаме да използваме традиционен IO за изграждане на сървър, той трябва да блокира някъде, така че трябваше да използваме цикъл или режим на една нишка и един сокет, така че nio изглежда е по-добър избор. Така че искам да знам дали nio е по-добрият избор завинаги?


person jiafu    schedule 15.10.2012    source източник
comment
Имате предвид New IO (преди java 7) или новия моден ребрандиран неблокиращ IO (docs.oracle.com/javase/7/docs/technotes/guides/io/)?   -  person RNJ    schedule 15.10.2012


Отговори (7)


IMHO, Блокирането на IO обикновено е най-простият за използване и освен ако нямате конкретно изискване, което изисква повече от вашата система, трябва да се придържате към най-простата опция.

Следващата най-проста опция е блокиране на NIO, което често предпочитам, ако искам нещо повече ефективност или контрол от IO. Все още е относително прост, но ви позволява да използвате ByteBuffers. напр. ByteBuffers поддържат little endian.

Обичайна опция е да се използва неблокиращ NIO със селектори. Голяма част от сложността, която това въвежда, може да се справи с рамки като Netty или Mina. Предлагам ви да използвате такава библиотека, ако имате нужда от неблокиращ IO, напр. защото имате хиляди едновременни връзки на сървър. IMHO Имате хиляди връзки, трябва да помислите за повече сървъри, освен ако това, което прави всяка връзка, е доста тривиално. AFAIK 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 благодаря много. Имам отворен поток от Twitter, би трябвало да чета 1000 съобщения в секунда, но по някаква причина получавам грешка, че техният буфер е достигнал лимита си. Като казвате, че използвате някакво буфериране, имате предвид IO буфери? - person Maroun; 22.04.2015
comment
@MarounMaroun в този случай, да. Коя граница достигнахте? Възможно ли е да четете съобщение, което не е пълно. Поток от байтове не разбира съобщенията само от байтове, така че когато четете от поток, можете да получите произволна част от съобщението, дори само един байт наведнъж. Как се справяте с това? - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey Аз просто чета BufferedReader#readLine (тъй като е обещано, че получавам всеки JSON като ред и това работи - всъщност виждам, че чета пълните JSON файлове на всяка итерация). Ограничението е от twitter: Принудително затваряне на връзката към **.*.**.**, защото е достигнато максимално допустимото архивиране (размерът на буфера е 311298 съобщения) (ако има нужда от помощ, коментарите ви притесняват, моля, уведомете ме :)) - person Maroun; 22.04.2015
comment
@MarounMaroun това означава, че Twitter ви е изпращал данни по-бързо, отколкото вие ги четете. Предлагам, след като прочетете реда, да не правите нищо повече в тази тема, освен да я добавите към BlockingQueue. Най-вероятно вашата програма за анализиране и обработка на съобщенията е била твърде бавна. - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey много благодаря, ще опитам това. Последен въпрос: Уместно ли е да увелича размера на буфера (сега използвам по подразбиране) и да го задам на нещо като 1MB? - person Maroun; 22.04.2015
comment
@MarounMaroun можете да направите това, но смисълът на опашката ни е, за да можете да видите, че изоставате и може би да предприемете коригиращи действия. Ако не успявате да се справите в дългосрочен план, повече буфериране и дори опашка няма да помогнат сами по себе си. Помощ за буфериране. ако получите изблици на активност и не можете да поддържате кратък период от време, но можете в дългосрочен план. Изглажда изблиците на активност. - person Peter Lawrey; 22.04.2015
comment
@PeterLawrey малка актуализация, може би ще помогне на други посетители.. част от проблема беше самата машина (приложението ми беше разгърнато на машина AWS t2.small, която не осигури добра мрежова производителност, след като преместих приложението на по-модерна машина, броят на грешките беше значително намален. - person Maroun; 26.04.2015

Ако искате неблокиращ IO, NIO не е по-добрият избор, той е единственият избор в Java. Имайте предвид, че хората все още използват стария IO редовно, защото е много по-лесно да се кодира срещу него. NIO API е доста суров и е по-скоро позволяваща технология на ниско ниво, отколкото API от страна на клиента. Предлагам да използвате NIO чрез API, който предоставя по-прост интерфейс за проблемите, които искате да разрешите, като използвате неблокиращ IO.

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. Old school методът е просто по-прост за използване и разбиране от неблокиращия асинхронен модел. - person Max; 15.10.2012
comment
@MyNameIsTooCommon Не означава нищо. Друг въпрос, ако използвате nio за подходящи задачи. - person Max; 15.10.2012
comment
@Max Ако съм прав, не разбирам всичко след „но“. - person user207421; 17.10.2012

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

  • Поддържа зависещи от файловата система атрибути.
  • Позволява ви да обхождате директно дърво на директория.
  • Поддържа символни връзки.

За конкретни случаи на употреба и повече подробности можете да видите това статия

person Imar    schedule 26.09.2018

Традиционният IO е лесен и опростен код, 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, мисля, че си прав :), но.. ако говорим за анализиране на файл и извличане на информация, във всеки случай с твоя метод ще направиш упражнението за клас в стария IO ^^ - person Andrea Bori; 09.04.2016