Руководство по API асинхронного канала Java NIO2
1. обзор
В этой статье мы собираемся изучить основы одного из ключевых дополнительных API-интерфейсов нового ввода-вывода (NIO2) в Java 7-asynchronous channel APIs.
Это первая в серии статей, которые будут освещать эту конкретную тему.
API-интерфейсы асинхронного канала являются усовершенствованием более ранних новых API-интерфейсов ввода-вывода (NIO), которые поставлялись с Java 1.4. Чтобы прочитать о селекторах NIO, следуйтеthis link.
Еще одним усовершенствованием API-интерфейсов NIO является новый API-интерфейс файловой системы. Вы также можете узнать больше о егоfile operations иpath operations на этом сайте.
Чтобы использовать асинхронные каналы NIO2 в наших проектах, мы должны импортировать пакетjava.nio.channels, поскольку в него включены необходимые классы:
import java.nio.channels.*;
2. Как работают API асинхронного канала
API асинхронного канала были введены в существующий пакетjava.nio.channels, проще говоря - путем добавления к именам классов префиксаAsynchronous.
Некоторые из основных классов включают:AsynchronousSocketChannel,AsynchronousServerSocketChannel иAsynchronousFileChannel.
Как вы, возможно, заметили, эти классы похожи по стилю на стандартные API канала NIO.
И большинство операций API, доступных для классов каналов NIO, также доступны в новых асинхронных версиях. Основное отличие состоит в том, чтоthe new channels enable some operations to be executed asynchronously.
Когда операция инициируется, API-интерфейсы асинхронного канала предоставляют нам две альтернативы для мониторинга и управления ожидающими операциями. Операция может вернуть объектjava.util.concurrent.Future или мы можем передать емуjava.nio.channels.CompletionHandler.
3. ПодходFuture
A Future object represents a result of an asynchronous computation. Предполагая, что мы хотим создать сервер для прослушивания клиентских подключений, мы вызываем статический APIopen дляAsynchronousServerSocketChannel и, при необходимости, привязываем возвращенный канал сокета к адресу:
AsynchronousServerSocketChannel server
= AsynchronousServerSocketChannel.open().bind(null);
Мы передалиnull, чтобы система могла автоматически назначать адрес. Затем мы вызываем методaccept на возвращенном сервереSocketChannel:
Future future = server.accept();
Когда мы вызываем методaccept дляServerSocketChannel в старом IO, он блокируется до тех пор, пока не будет получено входящее соединение от клиента. Но методaccept дляAsynchronousServerSocketChannel сразу возвращает объектFuture.
Универсальный тип объектаFuture - это тип, возвращаемый операцией. В нашем случае выше этоAsynchronousSocketChannel, но с тем же успехом это могло бытьInteger илиString, в зависимости от конечного типа возврата операции.
Мы можем использовать объектFuture для запроса состояния операции:
future.isDone();
Этот API возвращаетtrue, если базовая операция уже завершена. Обратите внимание, что завершение в этом случае может означать нормальное завершение, исключение или отмену.
Мы также можем явно проверить, была ли операция отменена:
future.isCancelled();
Он возвращаетtrue только в том случае, если операция была отменена до нормального завершения, в противном случае возвращаетсяfalse. Отмена производится методомcancel:
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 вызывается после успешного завершения операции ввода-вывода. Обратный вызовfailed вызывается, если операция не удалась.
Эти методы обратного вызова принимают другие параметры - чтобы мы могли передавать любые данные, которые, по нашему мнению, могут быть пригодны для тегирования вместе с операцией. Этот первый параметр доступен как второй параметр метода обратного вызова.
Наконец, ясный сценарий - использование одного и того жеCompletionHandler для разных асинхронных операций. В этом случае нам было бы полезно пометить каждую операцию, чтобы обеспечить контекст при обработке результатов, мы увидим это в действии в следующем разделе.
5. Заключение
В этой статье мы изучили вводные аспекты API асинхронного канала в Java NIO2.
Чтобы получить все фрагменты кода и полный исходный код для этой статьи, вы можете посетитьGitHub project.