本文主要目的是帮助大家更好的理解为什么NIO是N的而不是B的,不足之处欢迎来喷呦。
BIO 哪里B了
大家都知道BIO是Blocking IO的意思,如果你引用了java.io包下面的某个类去帮助你做不管是网络IO还是文件IO的操作,那么恭喜你,你的代码很B。你可能不服,我哪里B了,凭什么说我B???别急,follow me
以网络IO为例,大家通常会习惯用一些第三方框架,比方说 apache的HttpClient,可能在代码层次不大能触碰到B(BIO)的感觉,但其实这些框架底层实现都是基于Socket,有过Socket编程(java环境)经验的同学对下面这种写法应该不会陌生:
socket.getOuputStream();
socket.getInputStream();
这其实就是BIO B的源头。这里以大家常写的客户端代码为例,Socket连接建立以后,通过socket.getInputStream写请求的内容,此处socket会阻塞,写完之后socket.outPutStream取服务端返回的内容,此处也会阻塞,其实outPutStream会阻塞比想象中更久的时间,只要该方法开始调用,socket就会被阻塞,即使当前outPutStream中还没有接收到从服务器端返回的数据,所以这种BIO的socket是从连接建立到数据接收完这一整个过程全程阻塞。
NIO 咋就不B了呢
对java NIO来说,原有的input/outputstream被 Channel取代,Channel全双工,读写都能做 其实linux底层还是socket,相对于bio而言,nio只是更好的利用了linux操作系统 Channel全双工的特性
上面只是扯一扯,其实channel并不是nio非阻塞的关键(不关键你BB这么多)
NIO中原有的socket被SocketChannel代替,客户端要发送的数据写入ByteBuffer(Buffer有很多种,这只是比较常用的一个),通过Socket发出去,此时这个Socket不会阻塞在这里等着服务器端的响应,对java程序来说此时完全可以去做其他事情,不必像BIO一样阻塞在这里等着outPutStream里面有结果返回,此处即体现了NIO非阻塞的特点,那什么时候去拿服务器端返回的结果呢?这时候java NIO另一个特性就起作用了,Selector,我们可以起一个线程去轮询Selector(也可以不起线程,就地轮询,起了就是异步,不起就是同步),而Selector提供了几种方法去返回当前已经就绪的SocketChannel列表,底层利用了linux操作系统epoll的特性(暂时不考虑windows),epoll会以时间复杂度O(1)返回当前已经就绪即服务器端已经返回结果的SocketChannel列表。
再回到java NIO,得到当前就绪的SocketChannel列表后,就可以从各个有结果的Channel里读数据到BufferByte,如果是同步调用,这时候直接处理返回结果即可; 如果是异步调用,可以通过调用用户提供的回调函数的方式去处理返回结果。此处如果用户定义了回调函数,即是异步调用 如果用户线程等待NIO的返回结果,即无需定义回调函数,此时即为同步调用 因为是NIO 二者都是非阻塞调用 只是同步异步的区别而已。
以上就是为啥NIO不B的原因,其实只是大致说了一下过程,方便大家理解,想真正的了解掌握NIO这点东西肯定是不够的,me只是抛砖引玉,献丑一发。
Selector的几个方法:
public abstract Set<SelectionKey> keys(); // 获取当前就绪的SocketChannel列表 SelectionKey.channel public abstract Set<SelectionKey> selectedKeys(); // 非阻塞 获取当前是否有Channel就绪的状态标志 public abstract int selectNow() throws IOException; // 阻塞 带超时控制的 阻塞获取当前是否有Channel就绪的状态标志 public abstract int select(long var1) throws IOException; // 阻塞 直至当前有Channel就绪 public abstract int select() throws IOException;
不想用B了,想用NIO怎么办
上面说的都是原理性的东西,如果只是要会用NIO其实没必要完全搞懂原理(想成为大神还是去搞吧),推荐大家一个网络的NIO框架,也是apache出的,asynchttpclient,感兴趣的可以找一些相关资料用一用,还是很简单的。
结语
学海无涯苦做舟,今天的学习就到这里,有问题留言,想喷一喷的也come on。想玩LOL开黑的就不要找我了,我要学习,不能分心(pentaKill)。