NIO作为非阻塞框架,在多线程并发开发中应用比较广,现在让我们一起来深入的了解一下NIO框架。
首先确定一下文章的结构:
1.NIO的Buffer
2.NIO的管道Channel
3.NIO的选择器Selector,SelectionKey
4.NIO的编码
5.最后我们用一个例子来总结一下NIO的使用
一、NIO的Buffer
Buffer常用缓冲区数据类型
名称 | 描述 |
---|---|
Buffer | 缓存数据结构的基类,实现了基本方法 |
ByteBuffer | 使用 byte作为的缓存数据结构的缓冲区 |
ByteOrder | A typesafe enumeration for byte orders. |
CharBuffer | 使用 char作为的缓存数据结构的缓冲区 |
DoubleBuffer | 使用 double作为的缓存数据结构的缓冲区 |
FloatBuffer | 使用 float作为的缓存数据结构的缓冲区 |
IntBuffer | 使用 int作为的缓存数据结构的缓冲区 |
LongBuffer | 使用 long作为的缓存数据结构的缓冲区 |
ShortBuffer | 使用 short作为的缓存数据结构的缓冲区 |
MappedByteBuffer | 内存映射缓冲区 |
buffer主要属性:
// 大小: mark <= position <= limit <= capacity
private int mark = -1; //位置标签
private int position = 0; //记录当前缓冲区读取或存放的位置
private int limit; //缓冲区还有多少数据
private int capacity; //缓冲区容量
Buffer主要方法:
/**
*将缓冲区数据读出
**/
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
/**
*标记当前位置,相当于备份
**/
public final Buffer mark() {
mark = position;
return this;
}
/**
*恢复到标记位置,相当于恢复备份
**/
public final Buffer reset() {
int m = mark;
if (m < 0)
throw new InvalidMarkException();
position = m;
return this;
}
接下来我们看一下ByteBuffer的主要方法:
/**
*初始化一个指定大小的ByteBuffer
**/
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
/**
*将byte数组封装成ByteBuffer
**/
public static ByteBuffer wrap(byte[] array,
int offset, int length)
{
try {
return new HeapByteBuffer(array, offset, length);
} catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException();
}
}
/**
*获取缓冲区内容
**/
public ByteBuffer get(byte[] dst) {
return get(dst, 0, dst.length);
}
/**
*写入缓冲区
**/
public final ByteBuffer put(byte[] src) {
return put(src, 0, src.length);
}
其他Buffer的使用方法基本和ByteBuffer一致,需要特别说明的是MappedByteBuffer,它直接将文件映射到内存中,读取速度会更快,不过在使用时会出现文件读入内存后,无法删除文件的问题,这个原因是因为文件引用的句柄没有释放的原因,这个问题在JDK中没有解决方案。
接下来我们来了解NIO的Channel.