W tym wykładzie poznamy selektor reprezentowany przez klasę Selector . Klasa znajduje się w pakiecie java.nio.channels , więc nie trzeba niczego pobierać ani konfigurować, aby z niej korzystać. Obiekt typu Selector może śledzić jeden lub więcej obiektów typu Channel , sprawdzać ich gotowość do odczytu/zapisu itp. I co najważniejsze: selektor potrzebuje jednego wątku, a nie jednego wątku na kanał.

Selektory tworzymy metodą static open :
Selector selector = Selector.open();
Następnie kanały można zarejestrować w obiekcie selektora:
SelectionKey key1 = channel1.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel2.register(selector, SelectionKey.OP_WRITE);
Drugi parametr metody register określa, jaką operację będzie monitorował selektor. Jeśli chcesz monitorować kilka operacji jednocześnie, możesz użyć bitowego OR:
SelectionKey.OP_READ | SelectionKey.OP_WRITE
Gdy na którymś z kanałów wystąpi akcja I/O, selektor nas o tym powiadamia. W ten sposób możliwe jest np. odczytywanie danych z dużej liczby źródeł danych.
Należy tutaj zauważyć, że aby kanał mógł być używany z selektorem, musi być w tak zwanym trybie nieblokującym:
channel1.configureBlocking(false);
channel2.configureBlocking(false);
SelectionKey key1 = channel1.register(selector, SelectionKey.OP_READ);
SelectionKey key2 = channel2.register(selector, SelectionKey.OP_WRITE);
Wynika z tego, że selektor nie będzie działał z FileChannel , ponieważ FileChannel nie może zostać przełączony w tryb nieblokujący ( metoda configureBlocking jest zadeklarowana w klasie SelectableChannel , a FileChannel jej nie dziedziczy).

Na diagramie widać, że selektory są odpowiednie do użycia z gniazdami. Będziemy z nimi pracować pod koniec drugiego modułu.
Klucz wyboru
Rejestrując kanał selektorem otrzymujemy obiektKlucz wyboru. Ten obiekt zawiera dane reprezentujące rejestrację kanału.
Z klucza możesz określić, czy kanał jest gotowy na określoną wartość:
key.isReadable()
key.isAcceptable()
key.isConnectable()
key.isWritable()
Z klucza możesz uzyskać odpowiedni kanał i selektor:
Channel channel = key.channel();
Selector selector = key.selector();
Możesz przyczepić dowolny przedmiot do klucza, aby śledzić go w przyszłości. Można to zrobić albo podczas rejestracji kanału (z trzecim argumentem), albo później:
-
Klucz SelectionKey = channel.register(selektor, SelectionKey.OP_ACCEPT, obiekt);
-
klucz.dołącz(obiekt);
W przyszłości możesz uzyskać dołączony obiekt z klucza:
Object object = key.attachment();
Wniosek
Po zarejestrowaniu kanałów selektorem możemy:
- dowiedzieć się, ile kanałów jest gotowych do wykonania określonych operacji;
- zablokować wykonywanie programu do momentu pojawienia się co najmniej jednego gotowego kanału;
- zdobądź wiele kluczy gotowych kanałów;
- i inne.
Na koniec drugiego modułu przetestujemy selektory w praktyce.
GO TO FULL VERSION