Java NIO - Selettore

Come sappiamo, Java NIO supporta transazioni multiple da e verso canali e buffer. Quindi, per esaminare uno o più canali NIO e determinare quali canali sono pronti per la transazione dati, ad esempio leggere o scrivere Java NIO fornire Selector.

Con Selector possiamo creare un thread per sapere quale canale è pronto per la scrittura e la lettura dei dati e potrebbe trattare quel particolare canale.

Possiamo ottenere l'istanza del selettore chiamando il suo metodo statico open()Dopo aver aperto il selettore dobbiamo registrare un canale in modalità non bloccante con esso che restituisce un'istanza di SelectionKey.

SelectionKey è fondamentalmente una raccolta di operazioni che possono essere eseguite con il canale oppure possiamo dire che potremmo conoscere lo stato del canale con l'aiuto della chiave di selezione.

Le operazioni principali o lo stato del canale rappresentato dal tasto di selezione sono:

  • SelectionKey.OP_CONNECT - Canale pronto per la connessione al server.

  • SelectionKey.OP_ACCEPT - Canale pronto ad accettare connessioni in entrata.

  • SelectionKey.OP_READ - Canale pronto per la lettura dei dati.

  • SelectionKey.OP_WRITE - Canale pronto per la scrittura dei dati.

La chiave di selezione ottenuta dopo la registrazione ha alcuni metodi importanti come indicato di seguito:

  • attach() - Questo metodo viene utilizzato per collegare un oggetto con la chiave. Lo scopo principale del collegamento di un oggetto a un canale è riconoscere lo stesso canale.

  • attachment() - Questo metodo viene utilizzato per mantenere l'oggetto collegato dal canale.

  • channel() - Questo metodo viene utilizzato per ottenere il canale per il quale viene creata la chiave specifica.

  • selector() - Questo metodo viene utilizzato per ottenere il selettore per il quale viene creata la chiave specifica.

  • isValid() - Questo metodo restituisce se la chiave è valida o meno.

  • isReadable() - Questo metodo afferma che il canale della chiave meteo è pronto per la lettura o meno.

  • isWritable() - Questo metodo afferma che il canale della chiave meteo è pronto per la scrittura o meno.

  • isAcceptable() - Questo metodo afferma che il canale della chiave meteo è pronto per accettare o meno la connessione in entrata.

  • isConnectable() - Questo metodo verifica se il canale di questa chiave ha terminato o non è riuscito a completare l'operazione di connessione socket.

  • isAcceptable() - Questo metodo verifica se il canale di questa chiave è pronto per accettare una nuova connessione socket.

  • interestOps() - Questo metodo recupera l'insieme di interessi di questa chiave.

  • readyOps() - Questo metodo recupera il set pronto che è il set di operazioni per cui il canale è pronto.

Possiamo selezionare un canale dal selettore chiamando il suo metodo statico select()Il metodo di selezione del selettore viene sovraccaricato come -

  • select() - Questo metodo blocca il thread corrente finché almeno un canale è pronto per gli eventi per i quali è registrato.

  • select(long timeout) - Questo metodo fa la stessa cosa di select () tranne che blocca il thread per un massimo di timeout millisecondi (il parametro).

  • selectNow() - Questo metodo non si blocca affatto, ma ritorna immediatamente con i canali pronti.

Anche per lasciare un thread bloccato che richiama il metodo di selezione,wakeup() metodo può essere chiamato dall'istanza del selettore, dopodiché il thread in attesa all'interno di select () tornerà immediatamente.

Infine possiamo chiudere il selettore chiamando close() che invalida anche tutte le istanze di SelectionKey registrate con questo selettore insieme alla chiusura del selettore.

Esempio

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();
         }
      }
   }
}