Java NIO
第一章 简介
1.缓冲区操作,以从磁盘读取数据为例子:进程使用read请求系统填满缓冲区,内核随机向磁盘硬件发出指令,要求磁盘读取数据并放入内核缓冲区(通过DMA,直接内存读取,无需CPU协助)。然后内核把内存空间缓冲区数据拷贝到进程执行时指定的缓冲区。
2.虚拟内存的好处:
a) 虚拟内存将地址指向物理内存地址,这样DMA便可以直接存储到物理用户空间。
b) 虚拟内存空间可以大于实际可用硬件内存。
3.文件锁定机制允许一个进程阻止其他进程存取某文件,用于事务隔离。文件锁定有两种方式:共享的和独占的。
第二章 缓冲区
1.Buffer抽象类是固定数量的容器。其子类包括CharBuffer、IntBuffer、DoubleBuffer、ShortBuffer、LongBuffer、FlootBuffer和ByteBuffer。
2.Buffer的属性:
a) Capacity:缓冲区能容纳的数据元素的最大数量。
b) Limit:缓冲区的第一个不能被读或者写的元素。或者说缓冲区现存元素的计数。
c) Position:下一个要被读或者写的元素的索引,位置会自动由相应的get和put函数更新。
d) Mark:备忘位置,调用mark()来设定mark=position,调用reset()设定position=mark。标记在设定前是未定义的。关系如下:0<=mark<=position<=limit<=capacity。
3.缓冲区API:capacity()、position()、limit()、mark()、reset()、clear()、flip()、rewind()、hasRemaining()。
4.翻转:Flip()方法将一个能够继续添加数据元素的填充状态的缓冲区翻转成一个准备读出元素的释放状态。等同于调用buffer.limit(buffer.position()).position(0)。Rewind()函数与flip类似,但是不修改limit属性,只是修改position为0。
5.释放:remaining()方法返回从当期位置到上界limit还剩余的元素数目,hasRemaining()返回是否缓冲区从当前位置到limit是否还有元素可读取。Clear并不清空缓冲数据,只是设置position为0并设置limit=capability。
6.读取释放代码:
package com.conan.nio;
import java.nio.CharBuffer;
public class BufferTest {
public static void main(String[]args) { testFillAndDrain(); }
static void testFillAndDrain() { String content = "Hello Buffer."; CharBuffer cb = CharBuffer.allocate(100); // fill for (int i = 0;i < content.length(); i++) { cb.put(content.charAt(i)); } // 翻转用于读取 cb.flip();
// drain while (cb.hasRemaining()) { System.out.println(cb.get()); }
// 释放 cb.clear();
}
} |
7.压缩:compact()的作用是:
a) 丢弃已经释放的数据,将未读取的数据移动到缓冲区位置为0的位置。
b) 是缓冲区对重新填充容量准备就绪,position指向移动后第一个需要put的位置,limit指向capacity的位置。
Compact()可以用于释放部分缓存区。
8.标记函数mark()用于记住一个位置然后调用reset()将其恢复。调用mark()之前mark变量是未定义的。
9.比较:缓冲区Buffer通过提供equals比较两个缓冲区是否相等(对象类型相同,均为缓存区类型并且缓存类型相同;两个对象都剩余相同数量的元素,容量可以不同,索引也可以不相同,但是缓冲区中剩余元素的数目必须相同;每个缓冲区中get()函数返回的剩余元素序列必须一致[从position到limit]),compareTo比较两个缓冲区。
10.Get()和put()方法通过指定参数支持批量读取和填充。
11.通过allocate(size)创建缓冲区,并适用私有的存储空间。如果想适用自定义的存储空间,可以使用wrap(T []array)。hasArray()返回该缓存区是否包含一个客村去的备份数组,array()返回该数组的引用,arrayOffset()返回缓冲区数据在数组中存储位置从开始位置的偏移量。
12.Duplicate()函数用于创建一个与原始缓冲区相似的新缓冲区。两个缓冲区共享数据元素,拥有相同的mark/position/capacity。asReadOnlyBuffer()函数生成只读缓冲区,不能调用put()。
13.Slice()创建一个从原始缓冲区当前位置开始的缓冲区,并且其容量是原始缓冲区的剩余元素数量(limit-position)。
14.布尔类型没有对应的缓冲区域类型。
15.字节缓冲区最大的不同是它可以作为通道Channel的源头或者目标。通过order()函数设置字节的大小端。Byte大小为1字节,char和short为两个字节,int和float为四个字节,long和double为八个字节。
16.字符缓冲区使用asXXXBuffer()创建具体类型的视图,结合XXX类型相占用的字节创建相应的缓冲区。通过putXXX和getXXX操作元素。
非常好的Java NIO学习材料
http://www.iteye.com/magazines/132-Java-NIO
PS:Java大牛的博客
Jakob Jenkov:http://tutorials.jenkov.com/