Java NIO - Selector


As we know that Java NIO supports multiple transaction from and to channels and buffer.So in order to examine one or more NIO Channel's, and determine which channels are ready for data transaction i.e reading or writing Java NIO provide Selector.

With Selector we can make a thread to know that which channel is ready for data writing and reading and could deal that particular channel.

We can get selector instance by calling its static method open().After open selector we have to register a non blocking mode channel with it which returns a instance of SelectionKey.

SelectionKey is basically a collection of operations that can be performed with channel or we can say that we could know the state of channel with the help of selection key.

The major operations or state of channel represented by selection key are −

  • SelectionKey.OP_CONNECT − Channel which is ready to connect to server.

  • SelectionKey.OP_ACCEPT − Channel which is ready to accept incoming connections.

  • SelectionKey.OP_READ − Channel which is ready to data read.

  • SelectionKey.OP_WRITE − Channel which is ready to data write.

Selection key obtained after registration has some important methods as mentioned below −

  • attach() − This method is used to attach an object with the key.The main purpose of attaching an object to a channel is to recognizing the same channel.

  • attachment() − This method is used to retain the attached object from the channel.

  • channel() − This method is used to get the channel for which the particular key is created.

  • selector() − This method is used to get the selector for which the particular key is created.

  • isValid() − This method returns weather the key is valid or not.

  • isReadable() − This method states that weather key's channel is ready for read or not.

  • isWritable() − This method states that weather key's channel is ready for write or not.

  • isAcceptable() − This method states that weather key's channel is ready for accepting incoming connection or not.

  • isConnectable() − This method tests whether this key's channel has either finished, or failed to finish, its socket-connection operation.

  • isAcceptable() − This method tests whether this key's channel is ready to accept a new socket connection.

  • interestOps() − This method retrieves this key's interest set.

  • readyOps() − This method retrieves the ready set which is the set of operations the channel is ready for.

We can select a channel from selector by calling its static method select().Select method of selector is overloaded as −

  • select() − This method blocks the current thread until at least one channel is ready for the events it is registered for.

  • select(long timeout) − This method does the same as select() except it blocks the thread for a maximum of timeout milliseconds (the parameter).

  • selectNow() − This method doesn't block at all.It returns immediately with whatever channels are ready.

Also in order to leave a blocked thread which call out select method,wakeup() method can be called from selector instance after which the thread waiting inside select() will then return immediately.

In last we can close the selector by calling close() method which also invalidates all SelectionKey instances registered with this Selector along with closing the selector.

Example

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