Java NIO - Sélecteur

Comme nous savons que Java NIO prend en charge plusieurs transactions depuis et vers les canaux et la mémoire tampon. Ainsi, afin d'examiner un ou plusieurs canaux NIO, et de déterminer quels canaux sont prêts pour la transaction de données, c'est-à-dire la lecture ou l'écriture de Java NIO fournissent Selector.

Avec Selector, nous pouvons créer un thread pour savoir quel canal est prêt pour l'écriture et la lecture de données et pourrait traiter ce canal particulier.

Nous pouvons obtenir une instance de sélecteur en appelant sa méthode statique open()Après avoir ouvert le sélecteur, nous devons enregistrer un canal en mode non bloquant avec lui qui renvoie une instance de SelectionKey.

SelectionKey est essentiellement une collection d'opérations qui peuvent être effectuées avec le canal ou nous pouvons dire que nous pourrions connaître l'état du canal à l'aide de la touche de sélection.

Les principales opérations ou l'état du canal représenté par la touche de sélection sont -

  • SelectionKey.OP_CONNECT - Canal prêt à se connecter au serveur.

  • SelectionKey.OP_ACCEPT - Canal prêt à accepter les connexions entrantes.

  • SelectionKey.OP_READ - Canal prêt à lire les données.

  • SelectionKey.OP_WRITE - Canal prêt à écrire des données.

La clé de sélection obtenue après l'enregistrement a quelques méthodes importantes comme mentionné ci-dessous -

  • attach() - Cette méthode est utilisée pour attacher un objet avec la clé. Le but principal de l'attachement d'un objet à un canal est de reconnaître le même canal.

  • attachment() - Cette méthode est utilisée pour conserver l'objet attaché du canal.

  • channel() - Cette méthode est utilisée pour obtenir le canal pour lequel la clé particulière est créée.

  • selector() - Cette méthode est utilisée pour obtenir le sélecteur pour lequel la clé particulière est créée.

  • isValid() - Cette méthode retourne si la clé est valide ou non.

  • isReadable() - Cette méthode indique que le canal de la clé météo est prêt à être lu ou non.

  • isWritable() - Cette méthode indique que le canal de la clé météo est prêt pour l'écriture ou non.

  • isAcceptable() - Cette méthode indique que le canal de la clé météo est prêt à accepter une connexion entrante ou non.

  • isConnectable() - Cette méthode teste si le canal de cette clé a terminé ou échoué à terminer son opération de connexion de socket.

  • isAcceptable() - Cette méthode teste si le canal de cette clé est prêt à accepter une nouvelle connexion socket.

  • interestOps() - Cette méthode récupère l'ensemble des intérêts de cette clé.

  • readyOps() - Cette méthode récupère l'ensemble prêt qui est l'ensemble des opérations pour lesquelles le canal est prêt.

Nous pouvons sélectionner un canal à partir du sélecteur en appelant sa méthode statique select()La méthode .Select du sélecteur est surchargée comme -

  • select() - Cette méthode bloque le thread actuel jusqu'à ce qu'au moins un canal soit prêt pour les événements pour lesquels il est enregistré.

  • select(long timeout) - Cette méthode fait la même chose que select () sauf qu'elle bloque le thread pendant un maximum de millisecondes de timeout (le paramètre).

  • selectNow() - Cette méthode ne bloque pas du tout, elle revient immédiatement avec les canaux prêts.

Aussi pour laisser un thread bloqué qui appelle la méthode de sélection,wakeup() La méthode peut être appelée à partir d'une instance de sélecteur, après quoi le thread en attente dans select () retournera immédiatement.

En dernier on peut fermer le sélecteur en appelant close() qui invalide également toutes les instances SelectionKey enregistrées avec ce sélecteur tout en fermant le sélecteur.

Exemple

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