剑指Offer(类库)——Java的IO机制

本文主要介绍一下BIO、NIO、AIO

Block-IO:基于字节流的InputStream和OutputStream,基于字符流的Reader和Writer,同时也包括Socket那些java.net包下的类等。

BIO的属性是同步阻塞的,优点就是写起来简单缺点是效率太低。
在这里插入图片描述
NonBlock-IO:在JDK4中引入了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中的数据拷贝到另外一个Channel
  • transferFrom:把另外一个Channel中的数据拷贝到FileChannel

该Channel避免了两次用户态和内核态之间的上下文切换,即“零拷贝”,效率较高。

NIO-Buffer

有以下几种类型,进行缓冲流的数据属性修饰:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
  • MappedByteBuffer

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的时候可以同时处理别的事情,那我们应该如何进一步加工处理结果呢?

  1. 基于回调:实现CompletionHandler接口,调用的时候触发回调函数;
  2. 返回Future:通过isDone()查看是否准备好,通过get()等待返回数据
    在这里插入图片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章