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
andBuffer
for modern Java I/O systems.