Selector

Selector is a part of Java NIO (New I/O) that allows a single thread to monitor multiple channels (SocketChannel, ServerSocketChannel) for events like read, write, or accept. It’s the backbone of scalable non-blocking I/O applications.

Commonly Used Methods

Simple Program: Selector with ServerSocketChannel

LotusJavaPrince and Mahesh want to create a simple server that accepts client connections using a Selector to demonstrate non-blocking behavior.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class SimpleSelectorExample {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.bind(new InetSocketAddress(5000));
        serverSocket.configureBlocking(false);
        serverSocket.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("Server started on port 5000...");

        while (true) {
            selector.select(); // Blocking until an event occurs
            Iterator<SelectionKey> keys = selector.selectedKeys().iterator();

            while (keys.hasNext()) {
                SelectionKey key = keys.next();
                keys.remove();

                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                    System.out.println("Client connected: " + client.getRemoteAddress());
                } else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(256);
                    int read = client.read(buffer);
                    if (read == -1) {
                        client.close();
                        System.out.println("Client disconnected.");
                    } else {
                        buffer.flip();
                        System.out.println("Received: " + new String(buffer.array()).trim());
                    }
                }
            }
        }
    }
}

Problem Statement (With LotusJavaPrince and Mahesh)

LotusJavaPrince and Mahesh run an online banking portal. They need a non-blocking notification server using Java NIO, where multiple banking terminals (clients) can connect and get real-time alerts for suspicious transactions using a single-threaded Selector-based server.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;

public class AlertNotificationServer {
    private static final Map<SocketChannel, Long> lastAlertTime = new HashMap<>();

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.bind(new InetSocketAddress(5050));
        serverSocket.configureBlocking(false);
        serverSocket.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("Banking Alert Server started by LotusJavaPrince and Mahesh...");

        while (true) {
            selector.select(1000); // Wait 1 sec
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keys.iterator();

            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();

                if (key.isAcceptable()) {
                    SocketChannel client = serverSocket.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                    lastAlertTime.put(client, System.currentTimeMillis());
                    System.out.println("New terminal connected: " + client.getRemoteAddress());
                }

                if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(256);
                    int read = client.read(buffer);

                    if (read == -1) {
                        lastAlertTime.remove(client);
                        client.close();
                        System.out.println("Terminal disconnected.");
                        continue;
                    }

                    buffer.flip();
                    String input = new String(buffer.array()).trim();
                    System.out.println("Terminal says: " + input);
                }
            }

            // Simulate periodic alerts
            long currentTime = System.currentTimeMillis();
            for (SocketChannel client : lastAlertTime.keySet()) {
                if (currentTime - lastAlertTime.get(client) > 5000) { // 5 seconds
                    sendAlert(client, "âš  Suspicious login detected. Please verify immediately.");
                    lastAlertTime.put(client, currentTime);
                }
            }
        }
    }

    private static void sendAlert(SocketChannel client, String message) {
        try {
            ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
            client.write(buffer);
        } catch (IOException e) {
            try {
                client.close();
            } catch (IOException ignored) {}
        }
    }
}

The Selector class in Java NIO is a key component for building scalable, non-blocking I/O applications. It allows a single thread to monitor multiple channels (like SocketChannel or ServerSocketChannel) for various events such as read, write, connect, and accept—making it a cornerstone of event-driven programming in Java.

Using a Selector, developers can:

  • Handle thousands of client connections with minimal thread usage,
  • Improve resource utilization and performance in I/O-intensive applications,
  • Respond only when channels are ready, avoiding inefficient polling or blocking.

It works seamlessly with non-blocking channels, enabling applications like chat servers, real-time data feeds, multiplayer games, and high-throughput web servers.

Key Benefits:

  • Single-threaded multiplexing for multiple channels,
  • Enables asynchronous I/O processing,
  • Reduces thread management overhead and improves scalability,
  • Core building block for reactive network applications.

In summary, the Selector:

  • Empowers efficient, event-driven designs,
  • Is ideal for applications with high concurrency requirements,
  • Completes the trio of NIO networking with Channel and Buffer for modern Java I/O systems.
Scroll to Top