java nio缓冲区源码,深入java NIO系列之缓冲区分析与源码解读(1)

标记、位置、限制和容量值遵守以下不变式:

0 <= 标记 <= 位置 <= 限制 <= 容量

线程安全:多个当前线程使用缓冲区是不安全的。如果一个缓冲区由不止一个线程使用,则应该通过适当的同步来控制对该缓冲区的访问。

缓冲区数据传输,缓冲区的标记和重置

/**

* 可以向通过ByteBuffer的各种方法put字节、字节数组

* 这个过程中,可以mark来标记当前的位置,mark需要小于当前position

* 可以通过limit限制put的位置

*

* 如果希望通过缓冲区获取字节流,那么首先需要flip翻转因为,通过flip方法会将

* 当前位置标记为limit,position恢复为0,

* 也可以通过reset()方法将当前位置恢复到标记位置

*

*/

asIntBuffer() 创建int类型视图缓冲区

/**

* 由于一个int类型的数据,占用4个字节,

* 向缓冲区中写入一个int值时,缓冲区会将一个包含给定int值的4个字节按照当前的字节顺序写入缓冲区的当前位置,然后将该位置加4

* getInt()用于从缓冲区的当前位置读取4个字节,根据当前的字节顺序将它们组成int值,缓冲区位置加4

*

* 视图缓冲区的容量 = 字节缓冲区中存在的元素数量除以视图中一个数据类型的数据量

* 视图缓冲区和原来的缓冲区共享数据元素,视图缓冲区和当前缓冲区保持独立的limit、position和capacity

* asIntBuffer()创建的视图缓冲区从ByteBuffer 的当前position开始

*/

public void asIntBuffer()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

bBuf.putInt(100);

bBuf.putInt(200);

bBuf.putInt(300);

System.out.println("缓冲区容量:"+bBuf.capacity());

IntBuffer intBuf = bBuf.asIntBuffer();

System.out.println("int类型视图缓冲区容量:"+intBuf.capacity());

bBuf.putInt(1000);

bBuf.putInt(2000);

bBuf.putInt(3000);

bBuf.putInt(4000);

bBuf.flip();

bBuf.limit(41);

bBuf.putInt(5000);

bBuf.putInt(6000);

System.out.println(bBuf.getInt());

System.out.println(bBuf.getInt());

System.out.println(bBuf.getInt());

System.out.println(bBuf.getInt());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

intBuf.put(2);

intBuf.flip();

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println(intBuf.get());

System.out.println("intBuf容量:"+intBuf.capacity());

}

allocate()和allocateDirect() (创建直接缓冲区和非直接缓冲区)

/**

* 非直接内存缓冲区与直接内存缓冲区的区别:

* 直接内存缓冲区:直接缓冲区使用的内存由操作系统直接分配,不受JVM堆栈的支配

*

*非直接内存缓冲区:ByteBuffer.allocate() 在堆内存中创建,如果向一个通道中传入一个非直接ByteBuffer用于写入,

*通道可能会进行如下隐含操作:

*在通道中创建临时缓冲区,将非直接ByteBuffer中的内容复制到临时缓冲区中,执行低层次IO操作,

*当对象离开作用域时,变成无用数据,等待清理

*

*/

/**

* 创建直接内存缓冲区

* @param capacity

* @return

*/

public static ByteBuffer allocateDirect(int capacity) {

return new DirectByteBuffer(capacity);

}

/**

* 创建非直接缓冲区

* @param capacity

* @return

*/

public static ByteBuffer allocate(int capacity) {

if (capacity < 0)

throw new IllegalArgumentException();

return new HeapByteBuffer(capacity, capacity);

}

compact() 对缓冲区进行压缩

/**

* 将缓冲区的当前位置和界限之间的字节(如果有)复制到缓冲区的开始处。

* 即将索引 p = position() 处的字节复制到索引 0 处,将索引 p + 1 处的字节复制到索引 1 处,依此类推,

* 直到将索引 limit() - 1 处的字节复制到索引 n = limit() - 1 - p 处。

* 然后将缓冲区的位置设置为 n+1,

* 并将其界限设置为其容量。如果已定义了标记,则丢弃它。

*

*/

public void compact()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

byte[] b = "hello world".getBytes();

bBuf.put(b,0,b.length);

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

bBuf.position(70);

bBuf.compact();

System.out.println(bBuf.position()+" "+bBuf.limit()+bBuf.capacity());

}

dumplicate()  创建当前缓冲区的共享缓冲区

/**

* 创建共享此缓冲区内容的新的字节缓冲区。 新缓冲区的内容将为此缓冲区的内容。

*此缓冲区内容的更改在新缓冲区中是可见的,反之亦然;这两个缓冲区的位置、界限和标记值是相互独立的。

*新缓冲区的容量、界限、位置和标记值将与此缓冲区相同。当且仅当此缓冲区为直接时,新缓冲区才是直接的,

*当且仅当此缓冲区为只读时,新缓冲区才是只读的。

*

*/

public void duplicate()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

byte[] b = "hello world".getBytes();

bBuf.put(b,0,b.length);

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

ByteBuffer sliceBuffer = bBuf.slice();

System.out.println(sliceBuffer.position());

}

slice() 创建当前缓冲区的共享子序列

/**

* 创建新的字节缓冲区,该缓冲区为原缓冲区的共享子序列

* 该缓冲区的操作对原缓冲区是可见的,反之亦然。两个缓冲区的保存各自独立的limit、position、capacity,

* 新缓冲区的内容将从此缓冲区的当前位置开始,

* 新缓冲区的位置将为零,其容量和界限将为此缓冲区中所剩余的字节数量,其标记是不确定的。

*/

public void slice()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

byte[] b = "hello world".getBytes();

bBuf.put(b,0,b.length);

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

ByteBuffer sliceBuffer = bBuf.slice();

bBuf.put("lallalallalallalalllaallalallallalalallalalalalla".getBytes());

bBuf.flip();

System.out.println(sliceBuffer.limit()-sliceBuffer.position());

byte[] sliceBytes = new byte[sliceBuffer.limit()-sliceBuffer.position()] ;

sliceBuffer.get(sliceBytes);

System.out.println(new String(sliceBytes));

}

wrap() 将字节数组包装到缓冲区中

/**

* 将字节数组包装到缓冲区中

*

* 缓冲区的容量为字节数组的长度,缓冲区位置为0,缓冲区的变化对字节数组是可见的。

*

*/

public void wrap()

{

byte[] b = "hello world world hello".getBytes();

ByteBuffer bBuf = ByteBuffer.wrap(b);

b[0] = 'a';

System.out.println(bBuf.position()+" "+bBuf.capacity()+" "+bBuf.limit());

System.out.println(new String(bBuf.array()));

}

arrayOffset() 返回缓冲区元素在底层数组中的偏移量

/**

* 返回此缓冲区中第一个元素在缓冲区底层实现数组中的偏移量,调用之前需要先调用hasArray()方法,判断此缓冲区是否有可访问的底层数 *组

*子缓冲从原缓冲区创建时的当前位置开始

*/

public void arrayOffset()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

byte[] b = "hello world".getBytes();

bBuf.put(b,0,b.length);

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

System.out.println("判断此缓冲区是否有底层实现的数组:"+bBuf.hasArray());

System.out.println(bBuf.arrayOffset());

bBuf.flip();

bBuf.get();

System.out.println(bBuf.arrayOffset());

}

asReadOnlyBuffer() 创建只读的缓冲区

/**

* 该缓冲区和原有的字节缓冲区共享数据元素,但只读,两个缓冲区保有独立的position,limit,capacity

*/

public void asReadOnlyBuffer()

{

ByteBuffer bBuf = ByteBuffer.allocate(512);

byte[] b = "hello world".getBytes();

bBuf.put(b,0,b.length);

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

bBuf.put("world hello zhe shi yi shou jian dan de xiao qing ge .".getBytes());

ByteBuffer asReadOnlyBuffer = bBuf.asReadOnlyBuffer();

asReadOnlyBuffer.put("hahaha".getBytes());

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值