首页 > 代码库 > Java - NIO
Java - NIO
NIO
面向流的IO体系一次只能处理一个字节/字符,效率低,且在数据源中没有数据时会阻塞线程。Java-4提供的新API,Non-blocking IO(New IO,面向块的IO体系)为所有的原始类型提供Buffer缓存支持。采用内存映射文件的方式处理输入输出,将文件或文件的一段区域映射到内存中,模拟OS中虚拟内存的概念,提高IO速度。
区别:
- IO:阻塞式IO,面向流、基于字节/字符流;
- NIO:非阻塞式IO,面向块(缓冲区)、基于通道/缓冲区,选择器;
Sun官方标榜的特性:
- 为所有的原始类型提供缓存(Buffer)支持;
- Java.nio.charset:字符集编码解码解决方案;
- Channel:一个新的原始I/O抽象;
- 支持锁和内存映射文件的文件访问接口;
- 提供多路非阻塞式(non-bloking)的高伸缩性网络I/O;
思路:分而治之、专人入则专门的任务,多路复用IO,解决处理速度的差异,避免阻塞带来的多进/线程间的上下文切换。
工作原理:
- 由一个专门的线程来处理所有的IO事件并负责分发;
- 事件驱动机制:事件到达时触发而不是同步的去监视事件;
- 线程通讯:线程之间通过wait、notify等方式通讯,保证每次上下文切换都是有意义的、减少无谓的线程切换;
NIO的核心的API:Channel,Buffer,Selector
Channel
通道,对传统IO系统的模拟,传输数据,但是双向的、可读可写,支持异步I/O。Channel对象通过IO流对象的getChannel()方法获得。其map()方法将“一块数据”映射到内存中。
- FileChannel:读写文件;
- SocketChanel:通过TCP向网络连接的两端读写数据;
- ServerSocketChannel:能够监听客户端发起的TCP连接并为每个TCP连接创建一个新的SocketChannel用于数据读写;
- DatagramChannel:以UDP向网络连接的两端读写数据;
Buffer
缓冲区,连续内存块、本质是数组,支持多种数据类型,数据读写中转站。顶层父类、抽象类,最常用的是ByteBuffer。一个buffer主要由position、limit、capacity三个变量控制读写过程:
- position:当前读取的单位数据位置/当前写入的单位数据数量;
- limit:最多能读多少单位数据,和之前写入的单位数据量一致/最多能写多少单位数据,和容量一致;
- capacity:buffer容量;
函数:
- clear():清空buffer(position=0,limit=capacity)
- flip():将写模式转换为读模式(重置position、limit参数),准备将buffer中的数据读出并写到channel中
- rewind():position重置为0,用于重复读
- mark() + reset():标记位置 + 复位到该位置
- compact():将未读取的数据拷贝到buffer的头部位(清除已读数据)
步骤:
- 将数据写入到Buffer
- 调用flip()方法
- 从Buffer中读取数据
- 调用clear()方法或compact()方法
内存映射文件I/O
一种读和写文件数据的方法,将文件中实际读取或写入的数据映射到内存中,速度更快。
MappedByteBuffer类,继承于ByteBuffer类。
Selector
选择器,支持NIO非阻塞式、基于Reactor模式的工作方式,实现非阻塞I/O的核心对象是Selector。允许单线程监听和处理多个Channel的事件。通过注册Channel事件到Selector,再调用方法select()获取到达的事件并对事件响应处理。
SelectionKey
一个SelectionKey表示一个到达事件,包含事件的状态信息以及对应的通道的绑定。
参考:
- Java NIO:NIO概述; Java NIO原理分析;
- 一个故事讲清楚NIO;
- Java NIO:迟迟登场的NIO;
- Java NIO 系列教程;
Java - NIO