Java NIO 的 Selector:
- java 的 NIO,用非阻塞的 IO 方式,可以用一个线程,处理多个的客户端连接,就会使用到 Selector(选择器)
- Selector 能够检测多个注册通道上是否有事件发生(多个 Channel 以事件的方式可以注册到同一个 Selector ),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求
- 只有在连接/通道真正读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程
- 避免了多线程之间的上下文切换导致的开销
java.nio.channels.Selector 接口的常用方法:
- static Selector open() throws IOException:得到一个选择器对象
- Set
selectedKeys():从内部集合中得到所有的 SelectionKey - int select(long timeout) throws IOException:监控所有注册的通道,当其中有IO操作可以进行时,将对应的selectionKey加入到内部集合中并返回,参数用来设置超时时间
NIO 非阻塞网络编程相关的Selector、SelectionKey、ServerSocketChannel、SocketChannel 关系:
- 当客户端连接时,会通过 ServerSocketChannel 获得一个 SocketChannel
- 将 SocketChannel 注册到 Selector 上,即 register(Selector sel , int ops),一个 Selector 上可以注册多个 SocketChannel
- 注册后返回一个和该 Selector 关联的 SelectionKey
- 使用 Selector 的 select() 方法进行监听,返回有事件发生的通道的个数
- 然后得到 SelectionKey(有事件),然后 SelectionKey.channel() 得到 SocketChannel,通过得到的 channel,完成事件处理
Selector 的创建:Selector selector = Selector.open();
向 Selector 注册通道:SelectableChannel.register()
在与 Selector 一起使用时,Channel 必须处于非阻塞模式下,这意味着 Selector 不能和 FileChannel 连用,因为 FileChannel 不能切换到非阻塞模式,而套接字通道可以。
SelectionKey:
- Selector selector():得到与之关联的 Selector 对象
- SelectableChannel channel():得到与之关联的通道
- Object attachment():得到与之关联的共享数据(缓冲区)
- SelctionKey interestOps(int ops):设置或改变监听事件
- boolean isAcceptable():是否可以accept
- boolean isReadable():是否可以读
- boolean isWritable():是否可以写
四个事件常量:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
通道触发了一个事件的意思是该事件已经就绪,所以某个channel成功连接到另一个服务器称为“连接就绪”。一个server socket channel准备好接收新进入的连接称为“接收就绪”。一个有数据可读的通道可以说是“读就绪”。等待写数据的通道可以说是“写就绪”。当对不止一种事件感兴趣时,使用位或运算符连接,即“|”
ServerSocketChannel :在服务器端监听新的客户端 socket 连接
- static ServerSocketChannel open():得到一个 ServerSocketChannel 通道
- ServerSocketChannel bind(SocketAddress local):设置服务器端口
- SelectableChannel configureBlocking(boolean block):设置阻塞或非阻塞模式。true,阻塞模式;false,非阻塞模式
- SocketChannel accept():接受一个客户端连接,返回代表这个连接的通道对象
- SelectionKey register(Selector sel , int ops):注册一个选择器并设置监听事件