JAVA的I/O机制

BIO、NIO、AIO

BIO:Block-IO

  • 基于字节流和字符流进行操作

如InputStream和OutputStream,Reader和Writer

截屏2021-01-30 下午8.45.01

两端都会阻塞。

缺点:效率低

NIO:NonBlock-IO

构建多路复用的、同步非阻塞的IO操作

截屏2021-01-30 下午8.47.16

第一个阶段:程序不断询问内核是否数据准备完成,非阻塞

第二个阶段:拷贝数据阻塞等待

NIO核心:

  • Channels
  • Buffers
  • Selectors
截屏2021-01-30 下午8.49.49

Channel类似流,数据可以从Channel读到Buffer,也可以从Buffer写入Chennel

NIO-Channels
  • FileChannel
    • 其有两个方法:截屏2021-01-30 下午8.51.58
    • 避免了两次用户态和内核态间的上下文切换,即“零拷贝”,效率较高。
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel
NIO-Buffers
  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
  • MappedByteBuffer
NIO-Selector

selector允许单线程处理多个Channel:

截屏2021-01-30 下午8.55.39

Selector会一直阻塞,知道某个注册的Channel有事件就绪。

其底层使用了IO多路复用

IO多路复用:调用系统级别的select\poll\epoll
截屏2021-01-30 下午8.59.35
select、poll、epoll的区别
截屏2021-01-30 下午9.00.41

FD:文件句柄

截屏2021-01-30 下午9.02.36 截屏2021-01-30 下午9.03.23

AIO:Asynchronous IO

基于事件和回调机制

截屏2021-01-30 下午9.04.53

AIO如何进一步加工处理结果

有两种方法:

  • 基于回调:实现CompletionHandler接口,调用时出发回调函数。
  • 返回Future:通过isDone()查看是否准备好,通过get()等待返回数据。

BIO、NIO、AIO代码实例

BIO:

第一个server对每一个连接创建线程进行处理,第二个improvedServer做了提升,引入了线程池

image-20210130211114935

NIO:

  1. 首先通过ServerSocketChannel.open()创建一个server的channel

  2. 之后再从channel中获取ServerSocket实例

  3. 然后再将实例绑定到端口

  4. 将serverChannel阻塞状态设置为非阻塞

  5. Slector.open()创建一个selector,类似调度员的角色

  6. 将serverChannel注册到selector里

  7. 通过指定SelectionKey.OP_ACCEPT告诉调度员它关注的是新的连接请求,这儿也可以关注别的事件

  8. 没有连接前就自旋等待

  9. 。。。 后续看注释

image-20210130211511927

AIO

对比NIO来说更简单,只需调用API的read和write方法,其均为异步。

image-20210130212437457

BIO、NIO、AIO对比

截屏2021-01-30 下午9.28.50