博主知识水平有限,只能提供一个个人的狭隘的理解,如果有新人读到这儿,建议看一下其他教程或者 API,如果不明白,再来看一下;如果有 dalao 读到这儿,希望能指出理解中的问题~ 谢谢
Java 提供了用于网络通信的 socket 和 serversocket 包,然而实现方式是阻塞式的,同一时间点上只能进行一个连接,这会带来不好的体验。当然了,我们也可以通过不断创建线程的方式管理连接,但线程多了的话反而会降低效率。于是 Java 推出了非阻塞式 IO——channel。并且 channel 提供关于网络通信的相关 channel。
channel 将传统的输入输出流合并了,即一个 channel 既可以输入内容,也可以输出内容。
并且,使用 channel 的同时,要用 NIO 提供的 buffer 作为中介。
为了使用 socketchannel 与 serversocketchannel,请使用工厂模式创建 byteBuffer:
- ByteBuffer byteBuffer = ByteBuffer.allocate(12);
创建 Channel 方法:
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
下条语句将指定 channel 设为非阻塞式:
- serverSocketChannel.configureBlocking(false);
与某端口绑定:
- serverSocketChannel.bind(new InetSocketAddress(PORT));
相应的如果是 socketChannel,方法是 connect,这里仅拿 ServerSocketChannel 举例。
到此为止,我们还没有看到 channel 是如何实现非阻塞式 IO 的,于是 NIO 提供了一种工具——Selector。
Selector,简单来说,是对多个 channel 的管理工具,我们可以把多个 channel 一股脑加进去,如果哪个 channel 准备好读或者写(或者其他操作)就会通知我们。
Selector 中有一个 interest 的概念,意思是在我们把某个通道注册给 selector 时,我们指明 selector 要监视 channel 的哪一种行为,毕竟,一种 channel 可以 read,write,accept,connect。
Selector 实例化:
- Selector selector = Selector.open();
channel 注册
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
第二个参数为 interest 类型
一般的我们给 serverSocketChannel 注册一个 accept 就好。
然后,当我们调用 selector.select() 时,selector 会等待已经注册的 channel,直到有一个 channel 准备好。这个过程是阻塞式的,当然了阻塞又有什么关系呢,其实 IO 还是非阻塞式的。
之后我们引用 selector.selectedKeys() 会返回一个集合,包含了可以响应的 channel,迭代集合,我们得到一个个 channel。
噢,其实并不是得到 channel,而是另一种东西——SelectionKey。
SelectionKey 包含了挺多信息的,你可以得到他的 selector,channel 还有注册时的信息。
我们可以通过 selectionKey.isReadable,isAcceptable,isConnectable,isWritable 获得我们注册时的信息,然后具体的对每种响应类型处理。
还有,记得迭代完要把对象 remove 掉。
来源: http://www.bubuko.com/infodetail-1977670.html