От теории к практике: глубокая интерпретация преимуществ, недостатков и сценариев использования BIO, NIO и AIO.
От теории к практике: глубокая интерпретация преимуществ, недостатков и сценариев использования BIO, NIO и AIO.

BIO, NIO и AIO — это три разных механизма, используемых в языке программирования Java для обработки операций ввода и вывода (IO). Они представляют собой синхронный блокирующий ввод-вывод, синхронный неблокирующий ввод-вывод и асинхронный неблокирующий ввод-вывод соответственно.

BIO

BIO(Blocking IO) Это наиболее традиционная модель ввода-вывода, также известная как ввод-вывод с синхронной блокировкой. Он реализует модель синхронной блокировки, то есть режим реализации сервера — одно соединение и один поток, то есть, когда у клиента есть запрос на соединение, серверу необходимо запустить поток для обработки. Если это соединение ничего не делает, будут вызваны ненужные издержки потока, и поток будет заблокирован во время операции ввода-вывода и не сможет выполнять другие задачи. В среде с высоким уровнем параллелизма производительность BIO низкая, поскольку необходимо создавать поток для каждого соединения, а переключение потоков обходится дорого, но его можно улучшить с помощью механизма пула потоков. BIO подходит для некоторых простых, низкочастотных сценариев связи с коротким соединением, таких как HTTP-запросы.

БИО-модель

Преимущества и недостатки

преимущество:

  1. Простой и удобный в использовании: Метод программирования БИО-модели относительно прост и удобен для понимания и использования.
  2. Высокая надежность: Благодаря характеристикам блокировки результаты операций ввода-вывода являются надежными.

недостаток:

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

Пример кода

Код сервера:

Язык кода:javascript
копировать
import java.io.*;
import java.net.*;

public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        Socket clientSocket = null;

        try {
            //Создаем Сервер
            serverSocket = new ServerSocket(8888);
            System.out.println("Сервер запущен, ждём клиентсоединять...");

            while (true){
                // Слушайте запросы клиентов. Если запрос не получен, он будет ждать вечно.
                clientSocket = serverSocket.accept();
                int port = clientSocket.getPort();
                InetAddress inetAddress = clientSocket.getInetAddress();
                System.out.println("клиент "+inetAddress+":"+port+" соединятьуспех!");                //Обработка сообщения клиента
                new Thread(new ServerThread(clientSocket)).start();
            }
        } catch (IOException e) {
            System.out.println("клиентсоединятьнеудача:" + e.getMessage());
        } finally {
            try {
                if (clientSocket != null) {
                    clientSocket.close();
                }
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                System.out.println("Не удалось закрыть ресурс:" + e.getMessage());
            }
        }
    }
}

/**
 * Класс обработки потоков Сервера
 */
class ServerThread  implements Runnable{

    private Socket clientSocket;

    public ServerThread(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        //Получаем входной поток клиента для получения данных клиента
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            //Получаем поток вывода клиента для отправки данных клиенту
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream());

            int port = clientSocket.getPort();
            InetAddress inetAddress = clientSocket.getInetAddress();
            String address = inetAddress+":"+port;

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                //Получаем сообщение клиента
                System.out.println("клиент"+адрес+"Сообщение отправлено:" + inputLine);
                //Отправляем сообщение клиенту
                out.println("Сервер получил сообщение и ответил: "+inputLine);
                out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Код клиента:

Язык кода:javascript
копировать
public class BIOClient {
    public static void main(String[] args) throws IOException {
        Socket clientSocket = null;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            //Привязываем номер порта HTTPipи
            clientSocket = new Socket("localhost", 8888);
            System.out.println("соединять Серверуспех!");
            //Получаем входной поток и получаем сообщение Сервера
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            //Получаем выходной поток и отправляем сообщение на Сервер
            out = new PrintWriter(clientSocket.getOutputStream(), true);

            Scanner scanner = new Scanner(System.in);
            while (true){
                System.out.print("Отправить сообщение Серверу:");
                String msg = scanner.nextLine();
                out.println(msg);

                String response;
                if ((response = in.readLine()) != null) {
                    //Получаем ответ Сервера
                    System.out.println("Ответ сервера:" + response);
                }
            }
        } catch (IOException e) {
            System.out.println("соединять Сервернеудача:" + e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
                if (clientSocket != null) {
                    clientSocket.close();
                }
            } catch (IOException e) {
                System.out.println("Не удалось закрыть ресурс:" + e.getMessage());
            }
        }
    }
}

Результаты запуска:

Сервер

Клиент 1

Клиент 2

Приведенный выше код просто демонстрирует, как использовать БИО-модельодин Серверперениматьи обрабатывать несколькоклиент Статус запроса。Создано здесь3категории,соответственно Сервер BIOServer、многопоточностьклиенткласс обработкиServerThreadи клиентBIOClient,Затем запустите их отдельно СерверBIOServerидваклиентBIOClient,И получите строку ввода с клавиатуры в клиенте и отправьте ее на Сервер.,наконец Сервер Пучокперенимать Полученные данные затем возвращаются вклиент。

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

NIO

NIO — это новая модель ввода-вывода, представленная в Java 1.4, также известная как синхронный неблокирующий ввод-вывод. Она обеспечивает управляемый событиями способ обработки операций ввода-вывода.

По сравнению с традиционной БИО-моделью,NIO использует такие компоненты, как Channel, Buffer и Selector.,Потоки могут отслеживать события ввода-вывода,и продолжить выполнение других задач,Не нужно блокировать и ждать. Когда событие ввода-вывода готово,Тема будет уведомлена,Затем вы можете выполнить соответствующие операции,Реализует масштабируемую сетевую связь в стиле неблокирования. В модели НИО,Данные всегда считываются из канала в буфер.,Или напишите из буфера в канал,Этот режим повышает эффективность ввода-вывода.,И может полностью использовать системные ресурсы.

NIOВ основном состоит из трех частей:СелекторБуфериКаналChannelдаодин Может читать и записывать данныеизобъект,Все данные проходятBufferсправиться,Этот подход позволяет избежать записи байтов непосредственно в канал.,Вместо этого данные записываются в буфер, содержащий один или несколько байтов. В многопоточном режиме,Один поток может обрабатывать несколько запросов,Это делается путем регистрации запроса клиента на соединение на мультиплексоре.,Затем мультиплексор опрашивает обработку при поступлении запроса ввода-вывода от соединения.

Для НИО,Если посмотреть на характеристики,Это неблокирующий стиль IO,NдаNon-Blockingзначение;Если с технической точки зрения,NIO — новая технология для БИО,NзначениедаNewзначение。такNIOтакже часто называютNon-Blocking I/OилиNew I/O

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

Модель НИО

Преимущества и недостатки

преимущество:

  1. Высокий параллелизм: Используйте селекторы Канализ Модель НИО может обрабатывать несколько соединений в одном потоке, обеспечивая более высокую производительность параллелизма.
  2. Экономьте ресурсы: относительноBIO,NIO требует меньше потоков для обработки того же количества соединений.,Экономьте системные ресурсы.
  3. гибкость: NIOПредусмотрены различные типыизChannelиBuffer,Вы можете выбрать подходящий тип в соответствии с вашими потребностями. NIO позволяет разработчикам настраивать протоколы, кодеки и другие компоненты.,Тем самым улучшая гибкость и масштабируемость системы.
  4. высокая производительность: NIOна основе каналовибуферизспособ чтения и записи данных,Этот метод более эффективен, чем традиционный потоковый режим. Может уменьшить количество копий данных,Повышение эффективности обработки данных.
  5. Управление памятью:NIO允许用户手动管理буферизраспределение памятиипереработка,избегал традицииI/OМодельсерединаизпроблема с утечкой памяти。

недостаток:

  1. Программирование сложное: относительноBIO,Программирование NIO более сложное.,Необходимо понимать такие понятия, как селекторы и буферы.,Также необходимо учитывать проблемы многопоточности и синхронизации.
  2. Менее надежный: Модель НИОсередина,Операция чтения и записи соединения неблокирующая.,Нет никакой гарантии, что результаты операций ввода-вывода надежны.,Могут возникнуть частичные операции чтения и записи или ошибочные данные.

NIO подходит для некоторых сложных, высокочастотных сценариев связи с длительным соединением, таких как чаты, онлайн-игры и т. д.

Пример кода

Прежде чем смотреть код, сначала поймите 3 очень важных компонента NIO.,СелекторБуфер и Канал

  1. Канал:ChannelдаNIOсередина Используется для чтения и записи данных.издвусторонний канал,Данные можно считать из канала,Данные также можно записывать в каналы. Отличие от традиционного ввода-вывода,Канал двунаправленный,Операции чтения и записи могут выполняться одновременно.,И традицияизIOмогу только пройтиInputStreamилиOutputStreamВыполнение одностороннего чтения и записи。Java NIOсерединаобщийизChannelиметь:FileChannel(Чтение и запись файлов)、DatagramChannel(UDPпротокол)、SocketChannel(TCPпротокол)иServerSocketChannel(мониторTCPсоединятьпросить)ждать。
  2. Буфер: Буфер — это буфер, используемый для хранения данных в NIO. Его можно понимать как контейнер, из которого данные можно читать или записывать. Buffer имеет набор указателей для отслеживания текущей позиции, предела и емкости, а также других свойств. Ява NIOсередина Предусмотрены различные типыизBuffer,НапримерByteBufferCharBufferShortBufferIntBufferждать。каждый типизBufferВсеиметьсамоспецифичныйиз Методы чтения и письма.,Можно использоватьget()иput()ждатьметод来读写буферсерединаизданные。
  3. Селектор: SelectorдаNIOсередина Используется для мониторинга несколькихChannelизселектор,Может быть достигнуто управление одним потоком нескольких каналов. Селектор может определять, происходят ли события в нескольких каналах.,Включая такие события, как соединение, получение, чтение и запись.,И обрабатывать его соответствующим образом в соответствии с различными типами событий. Селектор может эффективно сократить использование ресурсов при управлении несколькими каналами в одном потоке.,Повышение эффективности работы программы.

Процесс работы НИО выглядит следующим образом:

  1. Откройте канал и Установите режим неблокирования。
  2. Зарегистрируйте канал в селекторе и укажите интересующий тип события (например, соединениеоткрыть, чтение и т. д.).
  3. 线程通过调用селекторизselect()методждать Подождите, пока событие произойдет。
  4. Когда происходит одно или несколько событий, поток может получить подготовленный канал от селектора и выполнить соответствующие операции ввода-вывода.
  5. После завершения операции ввода-вывода,Закрыть канал и селектор.

Следующие два фрагмента кода показывают процесс работы и использование NIO.

Код сервера:

Язык кода:javascript
копировать
public class NIOServer {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        // Создайте ServerSocketChannel и привяжите его к указанному порту.
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(9999));
        // Установите режим неблокирования
        serverSocketChannel.configureBlocking(false);
        // Зарегистрируйте ServerSocketChannel в Selector и прослушайте событие OP_ACCEPT
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("Сервер запущен, ожидает клиентсоединять...");

        while (true) {
            // Блокировать, ожидая возникновения события
            selector.select();

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                if (key.isAcceptable()) {     // Обработка события запроса на соединение
                    SocketChannel client = serverSocketChannel.accept();
                    client.configureBlocking(false);
                    //Прослушиваем событие OP_ACCEPT
                    client.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    client.getRemoteAddress();
                    //Выделяем емкость буфера
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    client.read(buffer);
                    String output = new String(buffer.array()).trim();

                    Socket socket = client.socket();
                    InetAddress inetAddress = socket.getInetAddress();
                    int port = socket.getPort();
                    String clientInfo = inetAddress+":"+port;
                    String message = String.format("отклиент %s , Сообщение: %s", clientInfo , output);
                    System.out.println(message);

                    System.out.print("Ответное сообщение: ");
                    writeMessage(selector, client, buffer);
                }

                keyIterator.remove();
            }
        }
    }

    private static void writeMessage(Selector selector, SocketChannel client, ByteBuffer buffer) throws IOException {
        Scanner scanner = new Scanner(System.in);
        String message = scanner.nextLine();
        buffer.clear();
        buffer.put(message.getBytes());
        //переключаемся из режима записи в режим чтения
        buffer.flip();
        while (buffer.hasRemaining()) {
            client.write(buffer);
        }

        //  Прослушайте еще раз событие OP_ACCEPT.
        client.register(selector, SelectionKey.OP_READ);
    }
}

Код клиента:

Язык кода:javascript
копировать
/**
 * @author Публичный аккаунт: Цензура(suncodernote)
 */
public class NIOClient {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("localhost", 9999));
        socketChannel.register(selector, SelectionKey.OP_CONNECT);

        while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                if (key.isConnectable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    if (client.isConnectionPending()) {
                        client.finishConnect();
                    }

                    System.out.print("Enter message to server: ");
                    Scanner scanner = new Scanner(System.in);
                    String message = scanner.nextLine();
                    ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
                    client.write(buffer);

                    client.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    client.read(buffer);
                    String output = new String(buffer.array()).trim();
                    System.out.println("Сообщение от клиента: " + output);

                    System.out.print("Входное сообщение: ");
                    // и Сервер Код тот же
                    writeMessage(selector, client, buffer);
                }
                keyIterator.remove();
            }
        }
    }
}

Результаты запуска:

серверная часть

сокол

Цангланг

Приведенный выше код создает два новыхкатегории:Сервер(NIOServer)иклиент(NIOClient),Вы можете узнать это с помощью приведенного выше кода и результатов выполнения.,При общении в Сервериклиенте,Мы не создавали новый класс потока для связи,Это также одно из самых больших различий между NIO и BIO.

Следует отметить, что,Хотя NIO повышает производительность параллелизма и масштабируемость системы,,Но это также приводит к увеличению сложности программирования и более сложным проблемам отладки. поэтому,При использовании Java NIO,Необходимо тщательно продумать применимые сценарии и модель программирования.

AIO

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

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

Модель AIO имеет следующие характеристики:

  1. Асинхронные возможности:AIOМодельизмаксимумхарактеристикада Асинхронные возможности, действительные для операций ввода-вывода сокетов. Операции чтения и записи являются асинхронными, и функция будет вызываться автоматически после завершения. обратного вызова。
  2. функция обратного вызова:существоватьAIOМодельсередина,Когда асинхронная операция завершается,Соответствующие потоки будут уведомлены для последующей обработки.,Этот тип обработки называется «обратным вызовом». Функция обратного вызова может быть определена разработчиком,Используется для обработки результатов асинхронных операций.
  3. неблокирующий:AIOМодельполностью осознализасинхронныйнеблокирующийIO,Не будет блокировать ни одну тему,Системные ресурсы можно использовать более эффективно.
  4. высокая производительность:потому чтоAIOМодельиз Асинхронные возможностиинеблокирующийхарактеристика,Он может лучше обрабатывать сценарии сетевых коммуникаций с высоким уровнем параллелизма и высокой масштабируемостью.,Дальнейшее повышение производительности и эффективности системы.
  5. Поддержка операционной системы:AIOМодель Требуется операционная системаизподдерживать,Поэтому в разных операционных системах оно может вести себя по-разному. Реализация настоящего асинхронного ввода-вывода была добавлена ​​после версии ядра Linux 2.6.

Преимущества и недостатки

преимущество:

  1. неблокирующий:AIOиз Основные преимуществадаэтоданеблокирующийиз。Это означаетсуществовать Когда выполняются операции чтения и записи,Программа может продолжать выполнять другие задачи。Это полезно, если вам нужно обрабатывать много параллелизма.соединятьизвысокая производительность очень полезна для серверов.
  2. Эффективный:потому чтоAIOМожет обрабатывать большие объемы параллелизмасоединять,Поэтому он обычно более эффективен, чем синхронный ввод-вывод (например, традиционный ввод-вывод Java и NIO).
  3. Упрощенная модель программирования:AIOиспользовалфункция обратного вызов, который делает программирование модели относительно простым. Когда операция завершена, она автоматически вызывается Function обратного вызова, программисту не нужно вручную проверять и ждать завершения операции.

недостаток:

  1. сложность:ХотяAIOизпрограммирование Модельотносительно простой,Но по своим характеристикам неблокирующий,Сложность программирования может увеличиться. Например,Необходимо обработать уведомление о завершении операции,и возможные проблемы параллелизма.
  2. Потребление ресурсов:AIOМожет потреблять большеиз Системные ресурсы。因为每个操作Все需要创建одинфункция обратного вызова,Если количество одновременных подключений очень велико,Может потреблять много системных ресурсов.
  3. портативность:AIOсуществовать Может быть недоступно на некоторых платформахилиплохая производительность。поэтому,Если вам нужна кроссплатформенная портативность,Возможно, потребуется рассмотреть возможность использования других входов/выходов.

AIO подходит для некоторых сценариев связи с экстремальными, сверхвысокими и сверхдлинными соединениями, таких как облачные вычисления, большие данные и т. д.

Следует отметить, что,В настоящее время модель AIO широко не используется.,Сетевые платформы, такие как Netty, по-прежнему основаны на модели НИО.

Пример кода

Сервер:

Язык кода:javascript
копировать
/**
 * @author Публичный аккаунт: Цензура(suncodernote)
 */
public class AIOServer {
    public static void main(String[] args) throws Exception {
        // Создает новый канал сокета асинхронного сервера, привязанный к указанному порту.
        final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
        System.out.println("Сервер запускается, ожидает клиентсоединять.");
        // Начните принимать новых клиентовсоединять
        serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
            @Override
            public void completed(AsynchronousSocketChannel clientChannel, Void att) {
                // Когда новое соединение будет завершено, снова примите новое клиентсоединять.
                serverChannel.accept(null, this);

                // Создайте новый буфер для чтения данных из
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                try {
                    InetSocketAddress clientAddress = (InetSocketAddress) clientChannel.getRemoteAddress();
                    InetAddress clientIP = clientAddress.getAddress();
                    int clientPort = clientAddress.getPort();
                    System.out.println("клиент "+ clientIP + ":" + clientPort + " соединятьуспех。");                } catch (IOException e) {
                    e.printStackTrace();
                }
                // Чтение данных из асинхронного канала сокета
                clientChannel.read(buffer, buffer, new ReadCompletionHandler(clientChannel));
            }
            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("Failed to accept a connection");
            }
        });
        // Держите сервер открытым
        Thread.sleep(Integer.MAX_VALUE);
    }
}

Чтение обработчика:

Язык кода:javascript
копировать
/**
 * @author Публичный аккаунт: Цензура(suncodernote)
 */
public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {

    private AsynchronousSocketChannel channel;

    public ReadCompletionHandler(AsynchronousSocketChannel channel) {
        this.channel = channel;
    }

    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        // Когда чтение завершится, переверните буфер и распечатайте его.
        attachment.flip();
        byte[] bytes = new byte[attachment.remaining()];
        attachment.get(bytes);
        System.out.println("Получено сообщение: " + new String(bytes , StandardCharsets.UTF_8));
        attachment.clear();

        // Чтение ввода с клавиатуры
        Scanner scanner = new Scanner(System.in);
        System.out.print("Входное сообщение: ");
        String message = scanner.nextLine();
        System.out.println();
        // Запись данных в асинхронный канал сокета
        channel.write(ByteBuffer.wrap(message.getBytes()));

        channel.read(attachment , attachment , new ReadCompletionHandler(channel));
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        System.out.println("Failed to read message");
    }
}

Клиент:

Язык кода:javascript
копировать
/**
 * @author Публичный аккаунт: Цензура(suncodernote)
 */
public class AIOClient {
    public static void main(String[] args) throws Exception {
        // Создайте новый канал асинхронного сокета.
        AsynchronousSocketChannel clientChannel = AsynchronousSocketChannel.open();

        // подключаться к серверу
        clientChannel.connect(new InetSocketAddress("localhost", 5000), null, new CompletionHandler<Void, Void>() {
            @Override
            public void completed(Void result,Void attachment) {
                System.out.println("соединятьприезжать Серверуспех。");            }
            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("Failed to connect server");
            }
        });
        
        // Чтение ввода с клавиатуры
        Scanner scanner = new Scanner(System.in);
        System.out.print("Отправить сообщение: ");
        String message = scanner.nextLine();

        // Запись данных в асинхронный канал сокета
        clientChannel.write(ByteBuffer.wrap(message.getBytes()), null, new CompletionHandler<Integer, Void>() {
            @Override
            public void completed(Integer result, Void attachment) {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                clientChannel.read(buffer, buffer, new ReadCompletionHandler(clientChannel));
            }
            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("Failed to write message");
            }
        });

        // Не отключать клиента
        Thread.sleep(Integer.MAX_VALUE);
    }
}

Результаты испытаний:

Серверный интерфейс:

Клиент 1:

Клиент 2:

Клиент 3:

выше Пример кодасередина,Связь через один Сервер(AIOServer) и 3 клиента(AIOClient),Простая демонстрация использования AIO. можно найти,Методы использования AIO и NIO в основном одинаковы.,Данные считываются из канала в буфер.,Или напишите из буфера в каналсередина,Разница в том, что AIO реализует асинхронный неблокирующий.

Подвести итог

BIO, NIO и AIO в Java обрабатывают операции ввода-вывода (I/O), но они различаются методами обработки и эффективностью.

  1. BIO(Blocking I/O):BIOда Самый традиционныйизI/OМодель,Все его операции блокируются. Это означает,Когда поток инициирует операцию ввода-вывода,Прежде чем переходить к другим задачам, необходимо дождаться завершения операции. поэтому,BIO менее эффективен при обработке больших объемов параллелизма.,Но его программирование простое.
  2. NIO(Non-blocking I/O):NIOданеблокирующийизI/OМодель,Это позволяет потокам выполнять другие задачи, ожидая завершения операций ввода-вывода. NIO представляет концепцию канала и буфера,и Селектор для мультиплексирования. NIO подходит для обработки больших объемов параллелизма.,Но его программирование относительно сложное.
  3. AIO(Asynchronous I/O):AIOданастоящийизасинхронныйI/OМодель,Приложениям не нужно ждать завершения операций ввода-вывода.,когда операция будет завершена,Операционная система уведомит приложение. AIO использует функцию обратного вызова или объекты Future для получения результатов операций.,Подходит для обработки больших объемов параллелизма.,Его программирование относительно простое.

Короче говоря, BIO и NIO и AIO имеют свои особенности. и недостатки, применимые сценарии также различны. BIO подходит для архитектур, где количество подключений небольшое и фиксированное. NIO подходит для сценариев, где количество подключений велико, но одновременных операций чтения и записи относительно мало. AIO подходит для сценариев, где количество подключений велико. и существует множество одновременных операций чтения и записи. При выборе того, какой ввод-вывод использовать, вам необходимо взвесить его с учетом конкретных сценариев и требований приложения. - END -

boy illustration
RasaGpt — платформа чат-ботов на основе Rasa и LLM.
boy illustration
Nomic Embed: воспроизводимая модель внедрения SOTA с открытым исходным кодом.
boy illustration
Улучшение YOLOv8: EMA основана на эффективном многомасштабном внимании, основанном на межпространственном обучении, и эффект лучше, чем у ECA, CBAM и CA. Малые цели имеют очевидные преимущества | ICASSP2023
boy illustration
Урок 1 серии Libtorch: Тензорная библиотека Silky C++
boy illustration
Руководство по локальному развертыванию Stable Diffusion: подробные шаги и анализ распространенных проблем
boy illustration
Полностью автоматический инструмент для работы с видео в один клик: VideoLingo
boy illustration
Улучшения оптимизации RT-DETR: облегченные улучшения магистрали | Support Paddle облегченный rtdetr-r18, rtdetr-r34, rtdetr-r50, rtdet
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | Деформируемое внимание с большим ядром (D-LKA Attention), большое ядро ​​​​свертки улучшает механизм внимания восприимчивых полей с различными функциями
boy illustration
Создано Datawhale: выпущено «Руководство по тонкой настройке развертывания большой модели GLM-4»!
boy illustration
7B превышает десятки миллиардов, aiXcoder-7B с открытым исходным кодом Пекинского университета — это самая мощная модель большого кода, лучший выбор для корпоративного развертывания.
boy illustration
Используйте модель Huggingface, чтобы заменить интерфейс внедрения OpenAI в китайской среде.
boy illustration
Оригинальные улучшения YOLOv8: несколько новых улучшений | Сохранение исходной информации — алгоритм отделяемой по глубине свертки (MDSConv) |
boy illustration
Второй пилот облачной разработки | Быстро поиграйте со средствами разработки на базе искусственного интеллекта
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция с нулевым кодированием и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
Решенная Ошибка | Загрузка PyTorch медленная: TimeoutError: [Errno 110] При загрузке факела истекло время ожидания — Cat Head Tiger
boy illustration
Brother OCR, библиотека с открытым исходным кодом для Python, которая распознает коды проверки.
boy illustration
Новейшее подробное руководство по загрузке и использованию последней демонстрационной версии набора данных COCO.
boy illustration
Выпущен отчет о крупной модели финансовой отрасли за 2023 год | Полный текст включен в загрузку |
boy illustration
Обычные компьютеры также могут работать с большими моделями, и вы можете получить личного помощника с искусственным интеллектом за три шага | Руководство для начинающих по локальному развертыванию LLaMA-3
boy illustration
Одной статьи достаточно для анализа фактора транскрипции SCENIC на Python (4)
boy illustration
Бросая вызов ограничениям производительности небольших видеокарт, он научит вас запускать большие модели глубокого обучения с ограниченными ресурсами, а также предоставит полное руководство по оценке и эффективному использованию памяти графического процессора!
boy illustration
Команда Fudan NLP опубликовала 80-страничный обзор крупномасштабных модельных агентов, в котором в одной статье представлен обзор текущего состояния и будущего агентов ИИ.
boy illustration
[Эксклюзив] Вы должны знать о новой функции JetBrains 2024.1 «Полнострочное завершение кода», чтобы решить вашу путаницу!
boy illustration
Краткое изложение базовых знаний о регистрации изображений 1.0
boy illustration
Новейшее подробное руководство по установке и использованию библиотеки cv2 (OpenCV, opencv-python) в Python.
boy illustration
Легко создайте локальную базу знаний для крупных моделей на основе Ollama+AnythingLLM.
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание решения. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Одна статья поможет вам понять RAG (Retrival Enhanced Generation) | Введение в концепцию и теорию + практику работы с кодом (включая исходный код).
boy illustration
Эволюция архитектуры шлюза облачной разработки
boy illustration
Docker и Kubernetes [Разработка контейнерных приложений с помощью Python]