1. Обзор
В этой статье мы рассмотрим основы одного из ключевых дополнительных API нового ввода – вывода (NIO2) в Java 7 – API асинхронного канала .
Это первая статья в серии статей, которые будут посвящены этой конкретной теме.
API асинхронного канала являются усовершенствованием более ранних новых API ввода-вывода (NIO), поставляемых с Java 1.4. Чтобы прочитать о селекторах NIO, перейдите по этой ссылке .
Еще одним усовершенствованием API NIO является новый API файловой системы. Вы также можете прочитать больше о его файловых операциях и операциях с путями на этом сайте.
Чтобы использовать асинхронные каналы NIO2 в наших проектах, мы должны импортировать пакет java.nio.channels , поскольку в него включены необходимые классы:
import java.nio.channels.*;
2. Как работают API асинхронных каналов
API – интерфейсы асинхронных каналов были введены в существующий пакет java.nio.channels , проще говоря, путем префикса имен классов со словом Асинхронный .
Некоторые из основных классов включают: AsynchronousSocketChannel , AsynchronousServerSocketChannel и AsynchronousFileChannel .
Как вы, возможно, заметили, эти классы похожи по стилю на стандартные API-интерфейсы NIOchannel.
Кроме того, большинство операций API, доступных классам NIOchannel, также доступны в новых асинхронных версиях. Основное отличие заключается в том, что новые каналы позволяют выполнять некоторые операции асинхронно .
Когда операция инициируется, API асинхронного канала предоставляют нам две альтернативы для мониторинга и управления ожидающими операциями. Операция может вернуть java.util.concurrent.Будущий объект или мы можем передать ему java.nio.channels.completionHandler .
3. Будущий Подход
Объект Future представляет собой результат асинхронного вычисления. Предполагая, что мы хотим создать сервер для прослушивания клиентских подключений, мы вызываем статический open API на AsynchronousServerSocketChannel и при необходимости привязываем возвращенный канал сокета к адресу:
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(null);
Мы передали null , чтобы система могла автоматически назначить адрес. Затем мы вызываем метод accept на возвращаемом сервере SocketChannel :
Futurefuture = server.accept();
Когда мы вызываем accept метод ServerSocketChannel в старом IO, он блокируется до тех пор, пока входящее соединение не будет получено от клиента. Но accept метод AsynchronousServerSocketChannel сразу же возвращает Future объект.
Общий тип объекта Future – это возвращаемый тип операции. В нашем случае выше это AsynchronousSocketChannel , но с таким же успехом это может быть Integer или String , в зависимости от конечного типа возврата операции.
Мы можем использовать объект Future для запроса состояния операции:
future.isDone();
Этот API возвращает true , если базовая операция уже завершена. Обратите внимание, что завершение в этом случае может означать обычное завершение, исключение или отмену.
Мы также можем явно проверить, была ли операция отменена:
future.isCancelled();
Он возвращает true только в том случае, если операция была отменена до завершения в обычном режиме, в противном случае он возвращает false . Отмена производится методом отмена :
future.cancel(true);
Вызов отменяет операцию, представленную объектом Future . Параметр указывает, что даже если операция началась, она может быть прервана. После завершения операции она не может быть отменена
Чтобы получить результат вычисления, мы используем метод get :
AsynchronousSocketChannel client= future.get();
Если мы вызовем этот API до завершения операции, он будет заблокирован до завершения, а затем вернет результат операции.
4. Подход completionHandler
Альтернативой использованию Future для обработки операций является механизм обратного вызова с использованием класса completionHandler . Асинхронные каналы позволяют указать обработчик завершения для использования результата операции:
AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open().bind(null); listener.accept( attachment, new CompletionHandler() { public void completed( AsynchronousSocketChannel client, Object attachment) { // do whatever with client } public void failed(Throwable exc, Object attachment) { // handle failure } });
API completed callback вызывается при успешном завершении операции ввода-вывода. Обратный вызов failed вызывается, если операция завершилась неудачно.
Эти методы обратного вызова принимают другие параметры – чтобы позволить нам передавать любые данные, которые, по нашему мнению, могут быть подходящими для маркировки вместе с операцией. Этот первый параметр доступен в качестве второго параметра метода обратного вызова.
Наконец, четкий сценарий – использование одного и того же completionHandler для разных асинхронных операций. В этом случае нам было бы полезно пометить каждую операцию, чтобы обеспечить контекст при обработке результатов, которые мы увидим в действии в следующем разделе.
5. Заключение
В этой статье мы рассмотрели вводные аспекты API асинхронных каналов Java NIO2.
Чтобы получить все фрагменты кода и полный исходный код для этой статьи, вы можете посетить проект GitHub .