NIO-缓冲区


缓冲区基础

缓冲区是对基本数据元素数组的封装对象,Buffer类及其专有的子类提供了用于处理数据缓冲区的API

缓冲区不是多线程安全的,多线程同时存取时,需要同步

  1. 属性

    • Capacity(容量): 缓冲区大小,创建时设定,不能更改
    • Limit(上界): 缓冲区现存元素数量
    • Position(位置): 下一个要被读或写的元素索引,位置会自动由相应的get()和put()函数更新
    • Mark(标记): 一个备忘位置,调用mark()来设定mark=position,调用reset()设定position=mark
    • 关系: 0 <= mark <= position <= limit <= capacity
  2. 缓冲区API

     public abstract class Buffer {
         public final int capacity()//容量
         public final int position()//返回下一个将要被读写的元素索引
         public final Buffer position (int newPosition)//设置下一个被读写元素的索引
         public final int limit()//返回缓冲区上界
         public final Buffer limit (int newLimit)//设置缓冲区上界
         public final Buffer mark()//设置标记mark=position
         public final Buffer reset()//重置读写位置position=mark
         public final Buffer clear()//重置为0,即limit=capacity,position=0
         public final Buffer flip()//翻转,将添加元素状态翻转成读取元素状态(相当于limit = position,然后position = 0然后开始读取写入的元素)
         public final Buffer rewind()//position=0,mark=-1
         public final int remaining()//返回剩余可读元素数量,当前位置到上界还剩余的元素数量
         public final boolean hasRemaining()//是否有剩余可读元素,即是否到达上界(limit)
         public abstract boolean isReadOnly();//是否只读
     }
  3. 存取

     public abstract class ByteBuffer extends Buffer implements Comparable{
         public abstract byte get();//取position位置
         public abstract byte get (int index);//取index位置
         public abstract ByteBuffer put (byte b);//存position位置开始
         public abstract ByteBuffer put (int index, byte b);//存index位置开始
         //...批量存取
     }
  4. 翻转

    • filp() : 翻转,将继续添加元素状态翻转成一个准备读取元素状态
    • 如果已经写入缓冲区,此时想要读取缓冲区内容,我们需将limit设置为当前位置position,然后将position重置为0,此时使用get()即可读取等价于: buffer.limit(buffer.position()).position(0)
    • 缓冲区翻转两次,实际可读取大小会变成0(limit=0,position=0)
  5. 释放

    • clear()将缓冲区重置为0,仅仅是limit = capacity,position=0,没有改变缓冲区内的任何数据元素
  6. 压缩/比较

     public abstract class ByteBuffer extends Buffer implements Comparable{
         public abstract ByteBuffer compact();//将未读元素移动到数组首
         public boolean equals (Object ob)//比较每个缓冲区剩余的内容是否相同(对象类型必须相同)
         public int compareTo (Object ob)//以字典顺序比较,可以比较大小
     }
  7. 创建缓冲区

    • CharBuffer,IntBuffer,DoubleBuffer,ShortBuffer,LongBuffer,FloatBuffer,ByteBuffer七种缓冲区创建方式相同,(MappedByteBuffer特殊)

      //以CharBuffer为例
      public abstract class CharBuffer extends Buffer implements CharSequence, Comparable{
        public static CharBuffer allocate (int capacity)//分配一个固定容量的缓冲区
        public static CharBuffer wrap (char [] array)//使用自定义的数组作为缓冲区
        public static CharBuffer wrap (char [] array, int offset,int length)//使用自定义数组作为缓冲区,并设置初始化位置(position)和长度(limit-position)
        public final boolean hasArray()//是否存在底层数组(allocate或wrap()创建的间接缓冲区底层都是数组)
        public final char [] array()//获取缓冲区底层数组(hasArray()返回false时不要使用,会抛异常)
        public final int arrayOffset()//返回缓冲区数据在数组中存储的开始位置偏移量
      
        //特有的
        public static CharBuffer wrap (CharSequence csq)//通过可读字符流创建缓冲区(实现Charsequence接口的类: String,StringBuffer等)
        public static CharBuffer wrap (CharSequence csq, int start,int end) //通过字符流的子序列创建缓冲区
      }
  8. 复制缓冲区

     public abstract class CharBuffer extends Buffer implements CharSequence, Comparable{
         //创建一个与原始缓冲区相似的新缓冲区,两个缓冲区共享数据元素,拥有同样容量,(相当于底层共用一个数组)
         //但拥有各自的position,limit,mark属性,一个缓冲区改变会反映到另一个缓冲区上,会继承只读或直接缓冲区属性
         public abstract CharBuffer duplicate();
         public abstract CharBuffer asReadOnlyBuffer();//同duplicate,不同的是改缓冲区只读,不能使用put()
         public abstract CharBuffer slice();
         //分割缓冲区,从源缓冲区position位置开始到limit位置结束创建一个新缓冲区
         //新缓冲区与原始缓冲区共享元素子序列,会继承只读和直接属性
     }

    字节缓冲区

  9. 字节顺序:

    • BIG_ENDIAN(大端字节顺序: 数字高->低位,存储内存地址低->高) , LITTLE_ENDIAN(小端字节顺序,Intel处理器使用小端字节顺序)
      public final class ByteOrder{
        public static final ByteOrder BIG_ENDIAN//大端字节顺序
        public static final ByteOrder LITTLE_ENDIAN//小端字节顺序
        public static ByteOrder nativeOrder()//获取本地字节顺序
      }
      public abstract class ByteBuffer extends Buffer implements Comparable{
        public final ByteOrder order()//查询字节顺序
        public final ByteBuffer order (ByteOrder bo)//设置字节顺序
      }
  10. 直接缓冲区

    • 直接缓冲区被用于与通道和固有I/O例程交互,它们通过使用固有代码来告诉操作系统直接释放或填充内存区域
      public abstract class ByteBuffer extends Buffer implements Comparable{
        public static ByteBuffer allocateDirect (int capacity)//分配直接字节缓冲区
        public abstract boolean isDirect();//是否直接缓冲区,如果底层是基于直接字节缓冲区的包装(wrap)缓冲区则也是true
      }
  11. 视图缓冲区

    • 视图缓冲区对象维护了自己的属性丶容量丶位置丶上界和标记,但是和原来的缓冲区共享数据元素
      //基于ByteBuffer缓冲区创建其视图缓冲区
      public abstract class ByteBuffer extends Buffer implements Comparable{
        public abstract CharBuffer asCharBuffer();
        public abstract ShortBuffer asShortBuffer();
        public abstract IntBuffer asIntBuffer();
        public abstract LongBuffer asLongBuffer();
        public abstract FloatBuffer asFloatBuffer();
        public abstract DoubleBuffer asDoubleBuffer();
      }
  12. 数据元素视图

    • ByteBuffer类提供了以多字节数据类型的形式存取byte数据组
      public abstract class ByteBuffer extends Buffer implements Comparable {
        public abstract char getChar();
        public abstract char getChar (int index);//从index位置开始取2字节char值
        public abstract int getInt();//从position位置开始取4字节int值
        public abstract int getInt (int index);
        //...等等
        public abstract ByteBuffer putFloat (float value);
        public abstract ByteBuffer putFloat (int index, float value);
        public abstract ByteBuffer putDouble (double value);
        public abstract ByteBuffer putDouble (int index, double value);
      }
  13. 内存映射缓冲区

    • 映射缓冲区是通过内存映射来存取文件中的数据元素的字节缓冲区,映射缓冲区通常是直接存取内存的,只能通过FileChannel类创建,用法和直接缓冲区类似,但是MappedByteBuffer对象可以处理独立与文件存取形式的许多特定字符

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
NIO-通道 NIO-通道
通道基础 基本 顶层的Channel接口,只有两个操作: 检查一个通道是否打开(isOpen())和关闭一个打开的通道(close())public interface Channel{ public boolean isOpen()
2019-09-12
下一篇 
并发-原子变量与非阻塞同步机制 并发-原子变量与非阻塞同步机制
原子变量 CAS操作 CAS(比较并交换)包含三个操作,需要读写的内存位置V丶进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子方式用新值B来更新V的值,否则不会执行任何操作,无论位置V的值是否等于A,都将返回V原
2019-09-06
  目录