В чём заключаются основные принципы работы Java NIO (New I/O)?

«В чём заключаются основные принципы работы Java NIO (New I/O)?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Java NIO (пакет java.nio) — это API для неблокирующего и буферизованного ввода-вывода, основанное на трёх ключевых абстракциях: Каналы (Channels), Буферы (Buffers) и Селекторы (Selectors).

Ключевые отличия от классического IO (java.io):

Аспект Классический IO (Потоки) NIO (Буферы/Каналы)
Модель Потоковая (stream-oriented) Буферизованная, блочная (buffer-oriented)
Блокировка Блокирующая (на время чтения/записи) Неблокирующий режим возможен
Мультиплексирование Нет (требует много потоков) Да (один поток через Selector может управлять многими каналами)

Основные компоненты:

  1. Буферы (Buffer)

    • Контейнер для данных. Основные операции: put(), get(), flip() (переключение на чтение), clear()/compact() (подготовка к записи).
  2. Каналы (Channel)

    • Двусторонний путь к устройству (файл, сокет). Реализации: FileChannel, SocketChannel, ServerSocketChannel.
  3. Селекторы (Selector)

    • Позволяют одному потоку проверять готовность множества каналов к операциям ввода-вывода.

Пример чтения файла с помощью FileChannel и ByteBuffer:

import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;

try (FileChannel channel = FileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ)) {
    ByteBuffer buffer = ByteBuffer.allocate(1024); // Выделяем буфер
    while (channel.read(buffer) != -1) { // Читаем данные в буфер
        buffer.flip(); // Меняем режим буфера с записи на чтение
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get()); // Читаем байты
        }
        buffer.clear(); // Очищаем буфер для следующей порции данных
    }
} catch (IOException e) {
    e.printStackTrace();
}

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