Java NIO - Selector

Como sabemos, Java NIO admite múltiples transacciones desde y hacia canales y búfer. Por lo tanto, para examinar uno o más canales NIO y determinar qué canales están listos para la transacción de datos, es decir, leer o escribir Java NIO, proporcione Selector.

Con Selector podemos hacer un hilo para saber qué canal está listo para escribir y leer datos y podría tratar ese canal en particular.

Podemos obtener una instancia de selector llamando a su método estático open()Después de abrir el selector, tenemos que registrar un canal en modo sin bloqueo con él que devuelve una instancia de SelectionKey.

SelectionKey es básicamente una colección de operaciones que se pueden realizar con el canal o podemos decir que podríamos conocer el estado del canal con la ayuda de la tecla de selección.

Las operaciones principales o el estado del canal representado por la tecla de selección son:

  • SelectionKey.OP_CONNECT - Canal que está listo para conectarse al servidor.

  • SelectionKey.OP_ACCEPT - Canal que está listo para aceptar conexiones entrantes.

  • SelectionKey.OP_READ - Canal que está listo para leer datos.

  • SelectionKey.OP_WRITE - Canal que está listo para escribir datos.

La clave de selección obtenida después del registro tiene algunos métodos importantes como se menciona a continuación:

  • attach() - Este método se utiliza para adjuntar un objeto con la llave. El propósito principal de adjuntar un objeto a un canal es reconocer el mismo canal.

  • attachment() - Este método se utiliza para retener el objeto adjunto del canal.

  • channel() - Este método se utiliza para obtener el canal para el que se crea la clave en particular.

  • selector() - Este método se utiliza para obtener el selector para el que se crea la clave particular.

  • isValid() - Este método devuelve si la clave es válida o no.

  • isReadable() - Este método indica que el canal de la clave meteorológica está listo para leer o no.

  • isWritable() - Este método indica que el canal de la clave meteorológica está listo para escribir o no.

  • isAcceptable() - Este método indica que el canal de Weather Key está listo para aceptar o no una conexión entrante.

  • isConnectable() - Este método prueba si el canal de esta clave ha finalizado o no ha finalizado su operación de conexión de socket.

  • isAcceptable() - Este método prueba si el canal de esta clave está listo para aceptar una nueva conexión de socket.

  • interestOps() - Este método recupera el conjunto de intereses de esta clave.

  • readyOps() - Este método recupera el conjunto listo, que es el conjunto de operaciones para las que está listo el canal.

Podemos seleccionar un canal del selector llamando a su método estático select().El método de selección del selector está sobrecargado como -

  • select() - Este método bloquea el hilo actual hasta que al menos un canal esté listo para los eventos para los que está registrado.

  • select(long timeout) - Este método hace lo mismo que select () excepto que bloquea el hilo durante un máximo de milisegundos de tiempo de espera (el parámetro).

  • selectNow() - Este método no bloquea en absoluto, regresa inmediatamente con los canales que estén listos.

También para dejar un hilo bloqueado que llame al método de selección,wakeup() se puede llamar al método desde la instancia del selector, después de lo cual el hilo que espera dentro de select () regresará inmediatamente.

Por último podemos cerrar el selector llamando close() método que también invalida todas las instancias de SelectionKey registradas con este Selector junto con el cierre del selector.

Ejemplo

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