面试题答案
一键面试Selector机制工作原理
- 注册通道:首先,将一个或多个
SelectableChannel
(如SocketChannel
、ServerSocketChannel
)注册到Selector
上。注册时会指定一个SelectionKey
,它代表了通道和选择器之间的注册关系,并且可以附加一些感兴趣的事件。 - 事件轮询:
Selector
通过select()
方法开始轮询注册在其上的通道。这个方法会阻塞,直到至少有一个通道发生了注册时感兴趣的事件。select()
方法返回的是发生事件的通道数量。 - 获取事件:当
select()
方法返回后,可以通过selectedKeys()
方法获取一个Set<SelectionKey>
,这个集合包含了所有发生事件的通道对应的SelectionKey
。通过遍历这个集合,可以对每个发生事件的通道进行相应处理。处理完事件后,需要手动从selectedKeys
集合中移除已处理的SelectionKey
,否则下次轮询时还会处理该事件。
检测通道上事件的方式
Selector
通过操作系统底层提供的机制(如Linux上的epoll、Windows上的IOCP等)来检测通道上的事件。操作系统会维护一个数据结构,记录所有注册的通道以及它们感兴趣的事件。当通道状态发生变化(如可读、可写等)时,操作系统会将对应的通道信息添加到一个就绪列表中。Selector
的select()
方法会询问操作系统这个就绪列表,获取发生事件的通道。
事件种类
- 可读事件(
SelectionKey.OP_READ
):表示通道中有新的数据可读。例如,SocketChannel
接收到了对方发送的数据,此时就会触发可读事件。 - 可写事件(
SelectionKey.OP_WRITE
):表示通道准备好可以写入数据。通常在通道的发送缓冲区有足够空间时触发,比如SocketChannel
在连接建立后,首次准备发送数据或者之前发送的数据已经成功传输,缓冲区有空间继续发送新数据时会触发可写事件。 - 连接建立事件(
SelectionKey.OP_CONNECT
):仅适用于SocketChannel
,表示连接操作已经完成。比如在使用SocketChannel
进行主动连接时,当连接成功建立,就会触发此事件。 - 接收连接事件(
SelectionKey.OP_ACCEPT
):仅适用于ServerSocketChannel
,表示有新的客户端连接到来,服务器端的ServerSocketChannel
可以接受这个连接。