在 java nio 中,op_read 用于注册 selector 以监听通道(channel)的可读事件。具体做法是调用 channel.register(selector, selectionkey.op_read),当有数据到达时,selector.select() 会返回并包含该键,随后通过 key.isreadable() 判断并读取数据。

如何正确注册 OP_READ 并处理连接建立
在服务器端,通常先注册 OP_ACCEPT,接受连接后,将新连接的通道注册为 OP_READ。这样 Selector 就能监控该通道的输入流状态。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class ReadExample {
public static void main(String[] args) throws IOException {
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
server.bind(new InetSocketAddress(8080));
Selector selector = Selector.open();
// 注册服务端通道,监听接受连接
server.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
if (selector.select() == 0) continue;
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
it.remove();
if (key.isAcceptable()) {
SocketChannel client = server.accept();
client.configureBlocking(false);
// 关键:注册 OP_READ 以监听数据到达
client.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = client.read(buffer);
if (read > 0) {
System.out.println("Received: " + new String(buffer.array(), 0, read));
// 重新注册 OP_READ 以继续监听
key.interestOps(SelectionKey.OP_READ);
}
}
}
}
}
}
OP_READ 与 OP_WRITE 的区别及适用场景
OP_READ 关注的是“是否有数据可读”,而 OP_WRITE 关注的是“缓冲区是否可写”。在处理大量小数据包或网络波动时,区分两者有助于优化性能。
立即学习“Java免费学习笔记(深入)”;

当 OP_READ 触发但读取结果为 -1 时意味着什么
如果 isReadable() 为真,但 channel.read() 返回 -1,这表示对端已经关闭了连接(EOF)。此时应关闭当前通道并从 Selector 中注销,避免无效循环。


















