Java NIO - Seletor

Como sabemos, o Java NIO suporta várias transações de e para canais e buffer. Assim, a fim de examinar um ou mais canais NIO e determinar quais canais estão prontos para a transação de dados, ou seja, ler ou gravar Java NIO fornecer Selector.

Com o Selector, podemos fazer um thread para saber qual canal está pronto para a gravação e leitura de dados e como lidar com aquele canal específico.

Podemos obter a instância do seletor chamando seu método estático open().Após o seletor aberto, temos que registrar um canal de modo sem bloqueio com ele, que retorna uma instância de SelectionKey.

SelectionKey é basicamente uma coleção de operações que podem ser realizadas com o canal ou podemos dizer que podemos saber o estado do canal com a ajuda da tecla de seleção.

As principais operações ou estado do canal representado pela tecla de seleção são -

  • SelectionKey.OP_CONNECT - Canal que está pronto para se conectar ao servidor.

  • SelectionKey.OP_ACCEPT - Canal que está pronto para aceitar conexões de entrada.

  • SelectionKey.OP_READ - Canal que está pronto para leitura de dados.

  • SelectionKey.OP_WRITE - Canal que está pronto para escrever dados.

A chave de seleção obtida após o registro possui alguns métodos importantes, conforme mencionado abaixo -

  • attach() - Este método é usado para anexar um objeto com a chave. O principal objetivo de anexar um objeto a um canal é reconhecer o mesmo canal.

  • attachment() - Este método é usado para reter o objeto anexado do canal.

  • channel() - Este método é usado para obter o canal para o qual a chave específica é criada.

  • selector() - Este método é usado para obter o seletor para o qual a chave específica é criada.

  • isValid() - Este método retorna se a chave é válida ou não.

  • isReadable() - Este método afirma que o canal da chave do tempo está pronto para leitura ou não.

  • isWritable() - Este método afirma que o canal da chave do tempo está pronto para gravação ou não.

  • isAcceptable() - Este método afirma que o canal da chave do tempo está pronto para aceitar a conexão de entrada ou não.

  • isConnectable() - Este método testa se o canal desta chave concluiu ou falhou ao concluir sua operação de conexão de soquete.

  • isAcceptable() - Este método testa se o canal desta chave está pronto para aceitar uma nova conexão de soquete.

  • interestOps() - Este método recupera o conjunto de interesse desta chave.

  • readyOps() - Este método recupera o conjunto pronto, que é o conjunto de operações para as quais o canal está pronto.

Podemos selecionar um canal do seletor chamando seu método estático select().Selecione o método do seletor está sobrecarregado como -

  • select() - Este método bloqueia o segmento atual até que pelo menos um canal esteja pronto para os eventos para os quais está registrado.

  • select(long timeout) - Este método faz o mesmo que select (), exceto que bloqueia o thread por um tempo máximo de milissegundos (o parâmetro).

  • selectNow() - Este método não bloqueia de forma alguma. Ele retorna imediatamente com quaisquer canais que estejam prontos.

Além disso, para deixar um tópico bloqueado que chama o método selecionado,wakeup() O método pode ser chamado a partir da instância do seletor, após a qual a thread esperando dentro de select () retornará imediatamente.

Por último, podemos fechar o seletor chamando close() que também invalida todas as instâncias de SelectionKey registradas com este Seletor, juntamente com o fechamento do seletor.

Exemplo

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