一、
1、NIO中我们可以使用一个线程来处理多个客户端连接,这时候就要使用selector了
2、Selector可以检测多个注册的通道上(可以理解为Selector里面有专门的数据结构存储这些注册的通道)是否有事件发生(多个channel以事件的方式可以注册到同一个selector)----如果有时间发生,便获取事件然后针对每个事件进行响应的处理。这样就可以只用一个单线程去管理多个通道了也就是管理多个请求和连接。
3、只有在 连接/请求 真正有读写事件发生的时候,才会进行读写,就大大减少了系统开销,,并且就不必为每个连接都单开一个线程,不用去维护多线程
4、避免了多线程的之间的上下文切换导致的开销
二、
关于selector的特点:
1、Netty中有一个io线程叫做--NioEventLoop,这个线程聚合了Selector,这样子就可以 同时并发的处理成百上千个客户端连接。
2、当线程从某客户端 Socket 通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。
3、线程通常将非阻塞 IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。
4、由于读写操作都是非阻塞的(缓冲区Buffer的作用),这就可以充分提升 IO线程的运行效率,避免由于频繁 I/O 阻塞导致的线程挂起。
5、一个 I/O 线程可以并发处理 N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞 I/O 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
三、
selector(抽象类)常用的一些方法:
public abstract class Selector implements Closeable {
①得到一个选择器对象
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
②监控所有注册的通道,当其中有IO操作可以进行时,将对应的SelectionKey(这里的SelectionKey是用来给Selector来找到channel)加入到内部集合中并返回,参数用来设置超时时间
public abstract int select(long timeout)----如果不加超时时间,那么就会阻塞,因为会一直监控,监控直到当前关注的channel有事件发生之后才会返回,但是加了超时时间之后,就只会阻塞timeout时间
但其实还有一个方法是selectNow(),马上监听,如果没有事件就马上返回
③从内部的集合中得到所有的selectionKey
public abstract Set<SelectionKey> selectedKeys();