Java高并发网络编程之NIO非阻塞网络编程

JAVA NIO

始于Java1.4,提供了新的JAVA IO操作非阻塞API。
用意是替代Java IO和Java Networking相关的API。

三大核心组件:

  1. Buffer缓冲区
  2. Channel通道
  3. Selector选择器

Buffer缓冲区

缓冲区本质上是一个可以写入数据的内存块(类似于数组),然后可以再次读取。此内存块包含在NIO Buffer对象中,该对象提供一组方法,可以更轻松地使用内存块。

相比较直接对数组的操作,Buffer API更加容易操作和管理。

使用Buffer进行数据写入和读取,需要进行如下四个步骤:

  1. 将数据写入缓冲区
  2. 调用buffer.flip(),转换为读取模式 flip:翻转
  3. 缓冲区读取数据
  4. 调用buffer.clear()或buffer.compact()清除缓冲区

Buffer工作原理

Buffer三个重要属性:

  1. capacity容量:作为一个内存块,Buffer具有一定的固定大小,也称为“容量”
  2. position位置:写入模式时代表写数据的位置。读取模式时代表读取数据的位置
    写模式:从什么地方开始写
    读模式:从什么地方开始读
  3. limit限制:写入模式,限制等于buffer的容量。读取模式下,limit等于写入的数据量
    写模式:能写到什么位置
    读模式:能读到什么地方

    Java高并发网络编程之NIO非阻塞网络编程
    Java高并发网络编程之NIO非阻塞网络编程

ByteBuffer内存类型

ByteBuffer为性能关键型代码提供了直接内存(direct堆外)和非直接内存(heap堆)两种实现。

堆外内存获取的方式:ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(noBytes);
好处:

  1. 进行网络IO或者文件IO时比heapBuffer少一次拷贝。(file/socket—OS memory—jvm heap)
    GC会移动对象内存,在写file或socket的过程中,JVM的实现中,会先把数据复制到堆外,再进行写入。

  2. GC范围之外,降低GC压力,但实现了自动管理。DirectByteBuffer中有一个Cleaner对象
    (PhantomReference),Cleaner被GC前会执行clean方法,触发DirectByteBuffer中定义的Deallocator

PS:堆外内存为直接内存,堆内存为JVM管理的内存(GC会影响到这部分内存的地址)

建议:

  1. 性能确实可观的时候才去使用;分配给大型、长寿命;(网络传输、文件读写场景)
  2. 通过虚拟机参数MaxDirectMemorySize限制大小,防止耗尽整个机器的内存;

Channel通道

Java高并发网络编程之NIO非阻塞网络编程
Java高并发网络编程之NIO非阻塞网络编程

SocketChannel

Java高并发网络编程之NIO非阻塞网络编程

ServerSocketChannel

Java高并发网络编程之NIO非阻塞网络编程
Java高并发网络编程之NIO非阻塞网络编程

Selector选择器

Java高并发网络编程之NIO非阻塞网络编程
Java高并发网络编程之NIO非阻塞网络编程

NIO对比BIO

Java高并发网络编程之NIO非阻塞网络编程
Java高并发网络编程之NIO非阻塞网络编程
Java高并发网络编程之NIO非阻塞网络编程

NIO与多线程结合的改进方案

Java高并发网络编程之NIO非阻塞网络编程

小结

Java高并发网络编程之NIO非阻塞网络编程