• java IO(六):NIO缓冲区 Buffer


    这篇引用自:https://blog.csdn.net/xialong_927/article/details/81044759

    在Java NIO中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(Channel)服务,写入数据到通道或从通道读取数据,这样的操利用缓冲区数据来传递就可以达到对数据高效处理的目的。(先将一块数据读取到内存创建的缓冲区中,运行时从内存缓冲区中取数据,即可大大提高读写效率,比如8192字节的缓冲区,若硬读写,那要读写8192次[假设一次1字节],但使用了缓冲区,读的时候,会将8192字节的数据一次性读到缓冲区中[只需要读取一次],写的时候,也只需要对缓冲区中的数据进行改变,再一次性写入外存)除了布尔类型,对于java的每种基本数据类型,都有对应的缓冲区。另MappedByteBuffer是专门用于内存映射的一种ByteBuffer。

    属性域:

    所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循:mark <= position <= limit <= capacity,下面是对这4个属性的解释:

    Capacity:

    容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变

    Limit :

    表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的

    Position :

    位置,下一个要被读或写的元素的索引,每次读写缓冲区数据时都会改变改值,为下次读写作准备

    Mark:

    标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置

    实例化:

    java.nio.Buffer类是一个抽象类,不能被实例化。Buffer类的直接子类,如ByteBuffer等也是抽象类,所以也不能被实例化。

    但是ByteBuffer类提供了4个静态工厂方法来获得ByteBuffer的实例:

    1)allocate(int capacity) :

    从堆空间中分配一个容量大小为capacity的byte数组作为缓冲区的byte数据存储器

    2)allocateDirect(int capacity) :

    是不使用JVM堆栈而是通过操作系统来创建内存块用作缓冲区,它与当前操作系统能够更好的耦合,因此能进一步提高I/O操作速度。但是分配直接缓冲区的系统开销很大,因此只有在缓冲区较大并长期存在,或者需要经常重用时,才使用这种缓冲区

    3)wrap(byte[] array) :

    这个缓冲区的数据会存放在byte数组中,bytes数组或buff缓冲区任何一方中数据的改动都会影响另一方。其实ByteBuffer底层本来就有一个bytes数组负责来保存buffer缓冲区中的数据,通过allocate方法系统会帮你构造一个byte数组

    4)wrap(byte[] array, int offset, int length):

    在上一个方法的基础上可以指定偏移量和长度,这个offset也就是包装后byteBuffer的position,而length呢就是limit-position的大小,从而我们可以得到limit的位置为length+position(offset)

    public static void main(String args[]) throws FileNotFoundException {
    
            System.out.println("----------Test allocate--------");
            System.out.println("before alocate:"
                    + Runtime.getRuntime().freeMemory());
    
            // 如果分配的内存过小,调用Runtime.getRuntime().freeMemory()大小不会变化?
            // 要超过多少内存大小JVM才能感觉到?
            ByteBuffer buffer = ByteBuffer.allocate(102400);
            System.out.println("buffer = " + buffer);
    
            System.out.println("after alocate:"
                    + Runtime.getRuntime().freeMemory());
    
            // 这部分直接用的系统内存,所以对JVM的内存没有影响
            ByteBuffer directBuffer = ByteBuffer.allocateDirect(102400);
            System.out.println("directBuffer = " + directBuffer);
            System.out.println("after direct alocate:"
                    + Runtime.getRuntime().freeMemory());
    
            System.out.println("----------Test wrap--------");
            byte[] bytes = new byte[32];
            buffer = ByteBuffer.wrap(bytes);
            System.out.println(buffer);
    
            buffer = ByteBuffer.wrap(bytes, 10, 10);
            System.out.println(buffer);
        }

    运行结果是:

    可以看到第一次创建的缓冲区,使用了JVM的内存(可用内存变小了),而第二次创建的缓冲区,直接使用系统内存,所以JVM的可用内存较上一次没有改变,接着使用wrap()创建的缓冲区,第一次直接传入数组byte,可以看到capacity和limit都是32,第二次设定了offset和length,于是初始position=offset=10,长度为10,所以limit=offset(position)+length=10+10=20。

  • 相关阅读:
    MD5加密
    HDU 1800 Flying to the Mars(Trie字典树 upper_bound)
    POJ 3624 Charm Bracelet(01背包 基础)
    hdu 1005 (规律 循环节)
    ZOJ 3710 friends(暴力 枚举 水)
    zoj 3714 Java Beans(枚举 水)
    hdu 1108 最小公倍数(数论基础 水)
    POJ 1797 Heavy Transportation(dijkstra )
    poj 3984 迷宫问题(bfs 打印路径)
    报数游戏(模拟 枚举)
  • 原文地址:https://www.cnblogs.com/MYoda/p/11196287.html
Copyright © 2020-2023  润新知