Java NIO - selektor
Ponieważ wiemy, że Java NIO obsługuje wiele transakcji zi do kanałów i buforów, więc w celu zbadania jednego lub więcej kanałów NIO i określenia, które kanały są gotowe do transakcji danych, tj. Odczyt lub zapis Java NIO, należy zapewnić Selector.
Dzięki Selectorowi możemy utworzyć wątek, aby wiedzieć, który kanał jest gotowy do zapisu i odczytu danych i może obsłużyć ten konkretny kanał.
Możemy uzyskać instancję selektora, wywołując jego metodę statyczną open().Po otwarciu selektora musimy zarejestrować kanał trybu nieblokującego, który zwraca instancję SelectionKey.
SelectionKey to po prostu zbiór operacji, które można wykonać za pomocą kanału lub możemy powiedzieć, że możemy poznać stan kanału za pomocą klawisza wyboru.
Główne operacje lub stan kanału reprezentowany przez klawisz wyboru to -
SelectionKey.OP_CONNECT - Kanał, który jest gotowy do połączenia z serwerem.
SelectionKey.OP_ACCEPT - Kanał, który jest gotowy do przyjmowania połączeń przychodzących.
SelectionKey.OP_READ - Kanał gotowy do odczytu danych.
SelectionKey.OP_WRITE - Kanał gotowy do zapisu danych.
Klucz wyboru uzyskany po rejestracji ma kilka ważnych metod, jak wspomniano poniżej -
attach() - Ta metoda służy do dołączania obiektu za pomocą klucza, a głównym celem dołączenia obiektu do kanału jest rozpoznanie tego samego kanału.
attachment() - Ta metoda służy do zatrzymania dołączonego obiektu z kanału.
channel() - Ta metoda służy do pobrania kanału, dla którego utworzono określony klucz.
selector() - Ta metoda służy do pobrania selektora, dla którego utworzono określony klucz.
isValid() - Ta metoda zwraca, czy klucz jest ważny, czy nie.
isReadable() - Ta metoda stwierdza, że kanał klucza pogody jest gotowy do odczytu lub nie.
isWritable() - Ta metoda stwierdza, że kanał klucza pogody jest gotowy do zapisu, czy nie.
isAcceptable() - Ta metoda stwierdza, że kanał klucza pogodowego jest gotowy do przyjęcia połączenia przychodzącego lub nie.
isConnectable() - Ta metoda sprawdza, czy kanał tego klucza zakończył lub nie zakończył operacji połączenia z gniazdem.
isAcceptable() - Ta metoda sprawdza, czy kanał tego klucza jest gotowy do przyjęcia nowego połączenia przez gniazdo.
interestOps() - Ta metoda pobiera zestaw odsetek dla tego klucza.
readyOps() - Ta metoda pobiera gotowy zestaw, czyli zestaw operacji, do których kanał jest gotowy.
Możemy wybrać kanał z selektora, wywołując jego statyczną metodę select().Select metoda selektora jest przeciążona jako -
select() - Ta metoda blokuje bieżący wątek, dopóki co najmniej jeden kanał nie będzie gotowy na zdarzenia, dla których jest zarejestrowany.
select(long timeout) - Ta metoda działa tak samo, jak select (), z tą różnicą, że blokuje wątek na maksymalny limit czasu w milisekundach (parametr).
selectNow() - Ta metoda nie blokuje się w ogóle, wraca natychmiast z wszystkimi kanałami, które są gotowe.
Również w celu pozostawienia zablokowanego wątku, który wywołuje metodę select,wakeup() metodę można wywołać z instancji selektora, po czym wątek oczekujący wewnątrz funkcji select () powróci natychmiast.
W końcu możemy zamknąć selektor, dzwoniąc close() , która również unieważnia wszystkie wystąpienia SelectionKey zarejestrowane za pomocą tego Selectora wraz z zamknięciem selektora.
Przykład
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();
}
}
}
}