Java NIO - Селектор
Как мы знаем, Java NIO поддерживает множественные транзакции между каналами и буфером. Итак, чтобы проверить один или несколько каналов NIO и определить, какие каналы готовы для транзакции данных, то есть для чтения или записи Java NIO предоставляет Selector.
С помощью Selector мы можем сделать так, чтобы поток знал, какой канал готов для записи и чтения данных, и мог бы работать с этим конкретным каналом.
Мы можем получить экземпляр селектора, вызвав его статический метод open(). После открытия селектора мы должны зарегистрировать в нем канал неблокирующего режима, который возвращает экземпляр SelectionKey.
SelectionKey - это в основном набор операций, которые могут быть выполнены с каналом, или мы можем сказать, что мы можем узнать состояние канала с помощью клавиши выбора.
Основные операции или состояние канала, представленные клавишей выбора, следующие:
SelectionKey.OP_CONNECT - Канал, готовый к подключению к серверу.
SelectionKey.OP_ACCEPT - Канал, готовый принимать входящие соединения.
SelectionKey.OP_READ - Канал, готовый к чтению данных.
SelectionKey.OP_WRITE - Канал, готовый к записи данных.
Ключ выбора, полученный после регистрации, имеет несколько важных методов, как указано ниже -
attach() - Этот метод используется для прикрепления объекта с ключом. Основная цель прикрепления объекта к каналу - распознавание того же канала.
attachment() - Этот метод используется для сохранения прикрепленного объекта из канала.
channel() - Этот метод используется для получения канала, для которого создан конкретный ключ.
selector() - Этот метод используется для получения селектора, для которого создан конкретный ключ.
isValid() - Этот метод возвращает верен ключ или нет.
isReadable() - Этот метод утверждает, что канал погодного ключа готов к чтению или нет.
isWritable() - Этот метод сообщает, что канал погодного ключа готов к записи или нет.
isAcceptable() - Этот метод утверждает, что канал погодного ключа готов к приему входящего соединения или нет.
isConnectable() - Этот метод проверяет, завершил ли канал этого ключа операцию подключения к сокету или не смог ее завершить.
isAcceptable() - Этот метод проверяет, готов ли канал этого ключа принять новое соединение сокета.
interestOps() - Этот метод извлекает интересующий набор этого ключа.
readyOps() - Этот метод извлекает готовый набор, который представляет собой набор операций, к которым готов канал.
Мы можем выбрать канал из селектора, вызвав его статический метод select().Select метод селектора перегружен как -
select() - Этот метод блокирует текущий поток, пока хотя бы один канал не будет готов для событий, для которых он зарегистрирован.
select(long timeout) - Этот метод делает то же самое, что и select (), за исключением того, что он блокирует поток на максимальное время ожидания в миллисекундах (параметр).
selectNow() - Этот метод вообще не блокируется, он немедленно возвращается, если каналы готовы.
Также, чтобы оставить заблокированный поток, который вызывает метод выбора,wakeup() Метод может быть вызван из экземпляра селектора, после чего поток, ожидающий внутри select (), немедленно вернется.
Наконец, мы можем закрыть селектор, вызвав close() , который также делает недействительными все экземпляры SelectionKey, зарегистрированные с помощью этого селектора, вместе с закрытием селектора.
пример
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SelectorDemo {
public static void main(String[] args) throws IOException {
String demo_text = "This is a demo String";
Selector selector = Selector.open();
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress("localhost", 5454));
serverSocket.configureBlocking(false);
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
ByteBuffer buffer = ByteBuffer.allocate(256);
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
int interestOps = key.interestOps();
System.out.println(interestOps);
if (key.isAcceptable()) {
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
client.read(buffer);
if (new String(buffer.array()).trim().equals(demo_text)) {
client.close();
System.out.println("Not accepting client messages anymore");
}
buffer.flip();
client.write(buffer);
buffer.clear();
}
iter.remove();
}
}
}
}