剑指Offer(类库)——JavaIO机制
在这篇文章总结完之后,就会进入Spring面试题整理和计算机网络面试题整理了,不知不觉还是挺快的。
这篇文章将主要介绍BIO、NIO、AIO
Block-IO:基于字节流的InputStream和OutputStream,基于字符流的Reader和Writer,同时也包括Socket那些java.net包下的类等等。
BIO的属性是同步阻塞的,优点就是写起来简单,缺点就是效率太低了
NonBlock-IO:在java4中引入了nio,它是一种构建多路复用的,同步非阻塞的IO操作,它提供了Selector Channel Buffer等新的抽象,同时提供了更底层的数据操作方式。
下面就来介绍一个NIO的三大核心:Channels,Buffers,Selectors。
-
NIO-Channel
Channel有点像流,一个的数据都是从Channel开始,然后读到Buffer中,再从Buffer写到Channel中。
NIO的Channels有以下几种类型,从方法名可以看出,有udp的Channel,有文件Channel,有tcp的Channel:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
其中,FileChannel中有两个有意思的方法:
transferTo
:把FileChannel中的数据拷贝到另外一个ChanneltransferFrom
:把另外一个Channel中的数据拷贝到FileChannel
该Channel避免了两次用户态和内核态之间的上下文切换,即“零拷贝”,效率较高。
- NIO-Buffer
有以下几种类型,进行缓冲流的数据属性修饰:
- NIO-Selector
如果连接打开了多个通道,但是每个通道的流量都很低,就可以使用Selector了。
另外NIO的底层也采用了IO的多路复用:调用系统级别的select/poll/epoll,意思也就是说,可以单线程处理多路IO。
然后简单介绍一下三者,以及三者的区别
select:单个进程能打开的最大连接数由FD_SETSIZE宏定义,其大小是32个整数的大小,我们可以对其进行修改,然后重新编译内核,但是性能无法保证,需要进一步测试
poll:本质上和select没有区别,但是没有最大连接数的限制,原因是因为他是基于链表去存储的
epoll:虽然连接数由上线,但是很大,1G内存的机器可以打开10万左右的连接
而面对文件句柄DF剧增之后也会带来IO效率问题
select:因为每次调用的时候都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度的线性下降的性能问题
poll:同上
epoll:由于epoll是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll不会有线性下降的性能问题,但是所有socket都很活跃的情况下,可能会有性能上的问题
在消息的传递方式上
select:内核需要将消息传递到用户空间,需要内核的拷贝工作
poll:同上
通过内核和用户空间共享一块内存来实现吗,性能很高
接着,jdk7又引入了AIO:基于事件和回调机制
AIO属于异步模型,也就是说,处理IO的时候可以同时处理别的事情,那我们应该如何进一步加工处理结果呢?
- 基于回调:实现CompletionHandler接口,调用的时候触发回调函数。
- 返回future:通过isDone()查看是否准备好,通过get()等待返回数据
对于以上三者: