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