Introduction to Java NIO components

Selector

Selector can detect events such as whether one or more channels are ready to read or write. In this way, a single thread can manage multiple channels (frequent thread switching is expensive for an operating system). Here is a schematic of a Selector handling three channels:

1 create the Selector

Selector selector = Selector.open();
Copy the code

Register a channel with a Selector

// Channel must be set to non-blocking mode to be used with Selector
channel.configureBlocking(false);
// The second argument is the set of events of interest
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
Copy the code

There are four types of event sets that can register multiple events of interest through or operations:

  • SelectionKey.OP_CONNECT
  • SelectionKey.OP_ACCEPT
  • SelectionKey.OP_READ
  • SelectionKey.OP_WRITE
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 
Copy the code

3 Return SelectionKey after registration

SelectionKey includes the following attributes:

  • The interest set: a collection of events of interest
  • The Ready Set: Which events are ready
  • The Channel: The Channel of registration
  • The Selector: The Selector at registration
  • An Attached Object (optional) : Attached object

4 Select a Channel using Selector

If you register multiple Channels with Selector, you can get ready Channels by selecting ().

  • Int select() : always blocking always Channel ready
  • Int SELECT (long timeout) : blocks for a specified time until the Channel is ready
  • Int selectNow() : does not block and returns immediately, whether the Channel is ready or not

Where the return value int represents how many channels are ready. After a Channel is ready, we can obtain the ready Channel by using selectedKeys() :

Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {  
    SelectionKey key = keyIterator.next();
    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
    // You must remove the SelectionKey yourself when you finish processing the channel, otherwise the next time the channel becomes ready, the Selector will put it in the selected key set again.
    keyIterator.remove();
}
Copy the code