Как new I/O (NIO) предлагает улучшить масштабируемость и повысить производительность?

Java долгое время не была предназначена для разработки программ, выполняющих множество операций ввода-вывода. А это означало, что такие общие вещи, как блокировка файлов, неблокирующие и асинхронные операции ввода-вывода, и возможность проецировать файл в память не были доступны. Неблокирующие операции ввода-вывода были достигнуты благодаря работе вокруг мультитрединга и использования JNI. New I/O API (NIO) в J2SE 1.4 в корне изменило ситуацию.
Способность сервера эффективно управлять многими клиентскими запросами зависит напрямую от того, как он использует потоки ввода-вывода. Когда серверу необходимо управлять сотнями клиентов параллельно, он должен иметь возможность использовать сервисы ввода-вывода параллельно. Одним из путей решения проблемы для этого сценария является использование потоков, но в отношении один-к-одному, что означает, что 100 клиентов будут иметь 100 потоков), который склонен к огромным затратам ресурсов и может пагубно сказаться на производительности и масштабируемости. Для преодоления этой пробемы, новый набор неблокуриющих классов ввода-вывода был представлен в пакете java.nio. Неблокирующий механизм ввода-вывода построен на основе селекторов и каналов (Selectors and Channels). Каналы, селекторы и буферы - ядро NIO.
- Channel класс представляет двунаправленный коммуникационный канал (аналог InputStream и OutputStream) между источниками данных, такими как сокет, файл, компонент приложения,который способен к выполнению одной или более операций ввода-вывода таких как чтение или запись. Хорошей новостью о каналах является то, что они могут быть асинхронно прерваны и закрыты. Поэтому, если поток заблокирован при выполнении операции ввода-вывода в канале, другой поток может прервать заблокированный поток.
- Selector класс разрешает мультиплексирование (multipexing)(комбинирование множества потоков в один поток) и демультиплексирование (demultiplexing)(разъединение одного потока в множество), что делает возможным обслуживание множества каналов ввода-вывода одним потоком. Селектор наблюдает за каналами, которые зарегистрированы для событий ввода-вывода таких как connect, accept, read, write. Ключи(Key1, Key2, которые представлены в классе SelectionKey) инкапсулируют взаимоотношения между специфическим каналом и селектором.
- Buffer содержит данные. Канал может заполнять и очищать буфер. Буферы заменяют потребность создания собственных буферов. Существует несколько типов буферов, таких как ByteBuffer, CharBuffer, DoubleBuffer.
Design pattern: NIO использует паттерн reactor, которые демультиплексирует события и доставляет их к зарегистрированному управляющему объекту. Паттер реактор похож на observer (также известный как publisher with multiple subscribers). Целью паттерна обзервер является определение зависимости один-к-многим, так что когда один объект изменяет его состояние, все зависимые объекты оповещаются об этом.
Другим искомым преимуществом после функционала NIO - возможность проецировать файлы в память. Есть специальный подвид буфера, известного как MappedByteBuffer, который представляет буфер байтов, спроецированных в файл. Для проецирования файла в MappedByteBuffer, вы должны сперва получить канал для файла. Как только получите канал, тогда можно проецировать файл в буфер и после этого можно доступаться к нему как к обычному ByteBuffer. Как только Вы спроецировали файл в CharBuffer, можно применять шаблоны поиска на содержимое файла. Это похоже на запуск команды grep в системах UNIX.
Еще одним преимущество NIO является возможность блокировки и разблокировки файлов. Блокировки могут быть выставляться как на весь файл, так и на порцию файла или другими словами - диапазон байт в файле. Но блокировки файлов - это уже обязанности операционной системы.
Материалы, которые могут вас заинтересовать
- Синхронизация потоков. Для чего предназначен метод join()?
- Как происходит взаимодействие между потоками? Как реализовать producer (один поток) и consumer (другой поток) для передачи данных через стек?
- Что такое daemon thread?
- Сихронизация потоков. В чем разница между синхронизацией метода и блока?
- Потоки в Java. Чем отличаются методы yield(), sleep(), wait()?
- Какие существует методы создания потоков (нитей)?
- Почему не рекомендуется отлавливать тип исключения “Exception”?
- Что такое приведение типов? Объясните up casting/down casting. Когда происходит ClassCastException?
- В чем преимущество операторов "&&, ||" над логическими "&, |"?







Спасибо, кратко и понятно. Только не совсем понятно про MappedFileBuffer. Если я изменяю данные в бужере эти данные будут автоматически перенесны в файл?
Отправить комментарий