NIO 设计背后的基石是反应器设计模式。 分布式系统中的服务器应用程序必须处理多个向它们发送服务请求的客户机。然而,在调用特定的服务之前,服务器应用程序必须将每个传入请求多路分用并分派到各自相应的服务提供者。反应器模式正好适用于这一功能。它允许事件驱动应用程序将服务请求多路分用并进行分派,然后,这些服务请求被并发地从一个或多个客户机传送到应用程序。
反应器模式与观察者模式(Observer pattern)在这个方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联
java NIO 的非阻塞 I/O 机制是围绕 选择器和 通道构建的。 Channel
类表示服务器和客户机之间的一种通信机制。与反应器模式一致, Selector
类是 Channel
的多路复用器。 Selector
类将传入客户机请求多路分用并将它们分派到各自的请求处理程序。
我们将仔细考察 Channel
类和 Selector
类的各个功能,以及这两个类如何协同工作,创建非阻塞 I/O 实现。
单靠 Channel
创建非阻塞 I/O 实现是不够的。要实现非阻塞 I/O, Channel
类必须与 Selector
类配合进行工作。
在反应器模式情形中, Selector
类充当 Reactor
角色。 Selector
对多个 SelectableChannels
的事件进行多路复用(selector 通过调用系统select poll epoll 等方法实现操作检测 (多路复用IO模型))。每个 Channel
向 Selector
注册事件。当事件从客户机处到来时, Selector
将它们多路分用并将这些事件分派到相应的 Channel
。
java window版JVM Selector实现方式:
线程在堵塞中等待有消息可读,当系统收到消息后,会去唤醒接收线程接收数据,在windows版的jdk下,这个唤醒,NIO是通过自己连接自己建立tcp连接(loopback)来通知读取线程的
linux下 是建立pipe ,通过pipe来通知
Windows下,Selector.open()会自己和自己建立两条TCP链接。不但消耗了两个TCP连接和端口,同时也消耗了文件描述符。
Linux下,Selector.open()会自己和自己建两条管道。同样消耗了两个系统的文件描述符
Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.EPollSelectorProvider jdk基于linux的epoll的实现