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