Java基础—NIO基础概念
Opened this issue · 0 comments
johnnian commented
一、I/O & NIO
Java的IO流,根据类型不同划分为(具体继承这些IO类的子类非常多)
- 基于字节操作的 I/O 接口:InputStream 和 OutputStream
- 基于字符操作的 I/O 接口:Writer 和 Reader
- 基于磁盘操作的 I/O 接口:File
- 基于网络操作的 I/O 接口:Socket
Java传统的IO类操作都是阻塞的,在高并发的场景下性能令人堪忧。
Java NIO(Non-blocking IO)是JDK1.4之后推出的一套新IO接口——非阻塞IO,与传统IO接口的主要区别在于:
I/O | NIO |
---|---|
线程阻塞 | 线程非阻塞 |
用流(Stream)的方式处理数据 | 用缓冲区(Buffer)的方式处理数据 |
二、NIO基本概念
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器)
2.1 Channel
1). Channel,相对于Stream,有几点区别:
Channel | Stream |
---|---|
双向(可以读写) | 单向(只能读或只能写) |
非阻塞操作 | 阻塞操作 |
基于Buffer | 基于流 |
2). NIO数据的流向总是:
Channel ----> Buffer
Channel <---- Buffer
3). Channel主要有下面几种类型:
类型 | 说明 |
---|---|
FileChannel | 文件的数据读写 |
DatagramChannel | UDP的数据读写 |
SocketChannel | TCP的数据读写 |
ServerSocketChannel | 监听TCP链接请求,并且创建SocketChannel |
4). 具体获取Channel的类
类型 | 说明 |
---|---|
FileChannel | FileInputStream.getChannel() FileOutputStream.getChannel() RandomAccessFile.getChannel() |
DatagramChannel | DatagramChannel.open() |
SocketChannel | SocketChannel.open() |
ServerSocketChannel | ServerSocketChannel.open() |
2.2 Buffer
Buffer实际上就是一块内存区,用于和Channel交互,需要注意的是:
Buffer是非线程安全的,如果需要在多线程环境中使用,则需要有同步锁。
1). Buffer基本概念
要真正理解Buffer,有一张图比较经典:
- capacity: buffer的容量大小,一般在创建之后就不会再改变;
- limit: buffer内存区中还未被读写的第一个element位置索引;
- position: 下一个等待要被读写的element位置索引;
- mark: 当调用reset方法时,position会被重置的位置索引;
通常,0 <= mark <= position <= limit <= capacity
2). Buffer类型
Buffer名字 | 对应基础类型 |
---|---|
ByteBuffer | byte |
CharBuffer | char |
DoubleBuffer | double |
FloatBuffer | float |
IntBuffer | int |
LongBuffer | long |
3). Buffer常用操作
buffer操作 | 具体 |
---|---|
clear() | limit=capacity, position=0, mark忽略 |
flip() | limit= position, position=0, mark忽略 |
rewind() | position=0, mark忽略 |
compact() (ByteBuffer才有) |
将整块Buffer(从position~limit)移动到Buffer开始的位置(0~limit-position) |
Buffer常用操作模式:
- 把数据写入buffer;
- 调用flip;
- 从buffer中读取数据;
- 调用buffer.clear()清空整个buffer 或者 buffer.compact()清空已经读取的buffer
2.3 Selector
Selector是NIO中的组件,检查一个或多个channel,实现一个线程管理多个网络链接。
使用步骤:
- 创建 selector
- 注册channel到selector
Channel必须是非阻塞的。所以FileChannel不适用Selector,因为FileChannel不能切换为非阻塞模式。Socket channel可以正常使用。