Как понять разницу между BIO, NIO и AIO?

Java

Во многих статьях просто приводится куча определений и несколько ярких примеров, когда речь идет о BIO, NIO и AIO. Кажется, хорошо понял. Однако самые основные сущностные принципы не раскрыты.Если нет отталкивания от принципа ИО, трудно понять разницу между тремя. Итак, эта статья начинается с анализа того, как Java выполняет операции ввода-вывода.

Принцип ввода-вывода в Java

Прежде всего, ввод-вывод в Java зависит от ядра операционной системы.Чтение и запись ввода-вывода в нашей программе фактически вызывают два основных системных вызова чтения и записи в ядре операционной системы.

Вот как с ним взаимодействует ввод-вывод ядра?

  1. Сетевая карта получает сетевые данные по сетевому кабелю и записывает сетевые данные в память.
  2. Когда сетевая карта записывает данные в память, сетевая карта отправляет сигнал прерывания на процессор, и операционная система может узнать о поступлении новых данных, а затем обработать данные с помощью программы прерывания сетевой карты.
  3. Запишите сетевые данные из памяти в приемный буфер соответствующего сокета.
  4. После записи данных в приемный буфер приложение начинает обработку данных.

Простой пример кода сокета, соответствующего абстракции для java, выглядит следующим образом:

public class SocketServer {
  public static void main(String[] args) throws Exception {
    // 监听指定的端口
    int port = 8080;
    ServerSocket server = new ServerSocket(port);
    // server将一直等待连接的到来
    Socket socket = server.accept();
    // 建立好连接后,从socket中获取输入流,并建立缓冲区进行读取
    InputStream inputStream = socket.getInputStream();
    byte[] bytes = new byte[1024];
    int len;
    while ((len = inputStream.read(bytes)) != -1) {
      //获取数据进行处理
      String message = new String(bytes, 0, len,"UTF-8");
    }
    // socket、server,流关闭操作,省略不表
  }
}

Можно видеть, что этот процесс очень похож на сетевой ввод-вывод базового ядра, который в основном отражается в accept(), ожидающем поступления запроса из сети, а затем массив bytes[] используется в качестве буфера для дождитесь заполнения данных перед обработкой. Разница между BIO, NIO и AIO заключается в том, являются ли эти операции синхронными или асинхронными, блокирующими или неблокирующими.

Итак, мы вводим понятия синхронного и асинхронного, блокирующего и неблокирующего.

Синхронный и асинхронный

Синхронный и асинхронный относится к тому, должен ли каждый метод в потоке выполнения зависеть от завершения предыдущего метода, прежде чем он сможет продолжить выполнение. Предположим, наш процесс выполнения: метод один и метод два по очереди.

Синхронизация означает, что после запуска вызова вызывающая сторона должна дождаться возврата вызова метода, прежде чем продолжить последующее поведение. То есть метод 2 должен дождаться выполнения метода 1, прежде чем его можно будет выполнить.

Асинхронность означает, что вызов возвращается немедленно, и вызывающая сторона может продолжить последующее поведение, не дожидаясь завершения выполнения кода в методе. (Код в конкретном методе может быть вызван обратно после его выполнения другим потоком). То есть, когда метод 1 выполняется, он напрямую передается другим потокам для выполнения, и он не выполняется основным потоком, поэтому он не будет блокировать основной поток, поэтому метод 2 не должен ждать, пока метод 1 завершается, чтобы начать выполнение.

Синхронизация и асинхронность фокусируются на том, является ли исполнителем метода основной поток или другой поток.Основной поток должен дождаться завершения выполнения метода, а другим потокам не нужно ждать немедленного возврата вызова метода, а основной поток может напрямую выполнять следующий код.

Синхронный и асинхронный - это достижение разницы в эффективности от координации между несколькими потоками.

Зачем нужна асинхронность? Автор считает, что суть асинхронности заключается в решении блокировки основного потока, поэтому во многих дискуссиях в Интернете было сделано четыре комбинации синхронной асинхронной и блокирующей неблокирующей.Одна из них имеет ситуацию асинхронной блокировки.Если асинхронная тоже блокирует? Итак, почему вы хотите выполнять асинхронные операции именно так?

блокирующий и не блокирующий

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

Блокировка означает, что после обнаружения ожидания синхронизации он ожидает, пока метод синхронизации завершит обработку на месте.

Неблокировка означает столкновение с синхронным ожиданием, а не ожидание на месте, сначала выполнение других операций, а затем наблюдение за тем, завершается ли метод синхронизации после времени блокировки.

Блокировка и неблокировка касаются того, ожидает ли поток на месте.

Автор считает, что блокировку и неблокировку можно сочетать только с синхронизацией. Асинхронный, естественно, неблокирующий, и этот неблокирующий предназначен для основного потока. (Некоторые люди могут подумать, что размещение блокирующей операции в асинхронном методе — это асинхронная блокировка, но подумайте об этом, именно потому, что это блокирующая операция, она помещается в асинхронный метод, не блокируйте основной поток)

Пример для объяснения

В Хайдилао вкусно, но часто бывают очереди. Давайте возьмем этот пример из жизни, чтобы объяснить.

  • Клиент А пошел есть хайдилао и просто сидел и ждал час, прежде чем съесть горячее. (БИО)
  • Покупатель Б пошел есть хайдилао.Он увидел, что ему придется долго ждать, поэтому он пошел в торговый центр, и каждый раз, когда он ходил по магазинам на некоторое время, он бежал обратно, чтобы посмотреть, стоит ли он в очереди. Так что в итоге он пошел по магазинам и съел Хайдилао. (НИО)
  • Клиент C пошел есть Haidilao, потому что он старший член, поэтому менеджер магазина сказал, что вы можете пойти в торговый центр, чтобы поиграть небрежно, и я сразу же позвоню вам, когда будет место. Таким образом, клиенту C не нужно сидеть и ждать, и ему не нужно время от времени возвращаться, чтобы посмотреть, могут ли они подождать, и, наконец, съесть Haidilao (AIO)

Какой способ эффективнее? Это очевидно с первого взгляда?

BIO

Полное название BIO — блокирующий ввод-вывод, который является традиционной моделью ввода-вывода до JDK1.4 и сам по себе является режимом синхронной блокировки. После того, как поток инициирует запрос ввода-вывода, он продолжает блокировать ввод-вывод до тех пор, пока данные буфера не будут готовы, а затем переходит к следующему шагу. Для сетевой связи это метод запрос-ответ.Хотя он упрощает разработку приложений верхнего уровня, существует огромное узкое место в производительности и надежности.Представьте, если для каждого запроса нужно создать новый поток для специальной обработки, то в высоких В параллельном сценарии ресурсы компьютера быстро исчерпываются.

NIO

NIO, также называемый неблокирующим вводом-выводом, представляет собой синхронную неблокирующую модель ввода-вывода. После того, как поток инициирует запрос ввода-вывода, он немедленно возвращается (неблокирующий ввод-вывод). Синхронизация означает, что вы должны дождаться готовности данных в буфере ввода-вывода. Неблокировка означает, что пользовательский поток не ждет, пока буфер ввода-вывода не будет готов. Сначала вы можете выполнить некоторые другие операции, но вам необходимо регулярно опрашивать проверьте, готовы ли данные буфера ввода-вывода. NIO в Java означает новый ввод-вывод. По сути, это NIO плюс технология мультиплексирования ввода-вывода. Обычный NIO — это опрос потока, чтобы узнать, готов ли буфер ввода-вывода, в то время как новый ввод-вывод в Java относится к опросу потоков, чтобы увидеть, какие из них готовы в группе буферов ввода-вывода, что является идеей мультиплексирования ввода-вывода. В модели мультиплексирования ввода-вывода задача проверки готовности данных ввода-вывода передается модели выбора или epoll на уровне системы, которая контролируется системой для снижения нагрузки на пользовательские потоки.

NIO в основном объединяет три технологии: буфер, канал и селектор.Данные получают через буфер с нулевым копированием, и каждый клиент регистрируется на селекторе (мультиплексоре) через канал. Сервер постоянно опрашивает канал, чтобы получить информацию о клиенте. На канале есть четыре флага состояния: подключение, принятие (блокировка), чтение (доступно для чтения) и запись (доступно для записи). Следите за идентификацией. Таким образом, сервер может принимать бесконечное количество каналов. Не нужно открывать новую тему. Значительно улучшена производительность.

AIO

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

AIO может выполнять настоящие асинхронные операции, но реализовать его сложнее.Операционных систем, поддерживающих чистый асинхронный ввод-вывод, очень мало.В настоящее время окна реализованы по технологии IOCP, а в Linux нижний слой по-прежнему реализован по epoll.

Личное понимание и резюме автора, если есть какие-либо ошибки, прокомментируйте и исправьте их.

Перейдите на мой личный блог vc2x.com