数据在网络中传输,必然回遇到读写问题....

2.比较NIO与IO

  NIO与网络编程系统化学习

 

3.案例演示

3.1.缓冲区演示

package com.wfd360.nio;

import org.junit.Test;

import java.nio.ByteBuffer;

public class BufferDemo {
    /**
     * 缓冲区(Buffer)
     * Buffer在Java NIO 中负责数据的存取,缓冲区就是数组,用于存储不同数据类型的数据。
     * <p>
     * 缓冲区类型
     * 根据数据类型的不同(boolean除外),提供了相应类型的缓冲区。
     * <p>
     * ByteBuffer
     * CharBuffer
     * ShortBuffer
     * IntBuffer
     * LongBuffer
     * FloatBuffer
     * DoubleBuffer
     * 上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区。
     * ByteBuffer最为常用
     * ————————————————
     * 缓冲区存取数据的两个核心方法
     * put():存入数据到缓冲区中
     * flip():切换到读取数据的模式
     * get():获取缓冲区中的数据
     * rewind():重复读,使position归0
     * clear():清空缓冲区,但是缓冲区中的数据依然存在,只是处于一种“被遗忘“的状态。只是不知道位置界限等,读取会有困难。
     * mark():标记。mark会记录当前的position,limit,capacity
     * reset():position,limit,capacity恢复到mark记录的位置
     * -------------------
     * 缓冲区的四个核心属性
     * capacity: 容量,表示缓冲区中最大存储数据的容量,一但声明不能改变。(因为底层是数组,数组一但被创建就不能被改变)
     * limit: 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
     * position: 位置,表示缓冲区中正在操作数据的位置
     * position <= limit <= capacity
     * mark:标记,表示记录当前position的位置,可以通过reset()恢复到mark的位置。
     * ———————————————
     */
    @Test
    public void test1() {
        //1.allocate():分配缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(128);
        //2.当前缓存区当前属性
        System.out.println("-----allocate(128)-------");
        print(byteBuffer);
        //3.放入数据
        String put = "123456";
        byteBuffer.put(put.getBytes());
        System.out.println("-----put()-------");
        print(byteBuffer);
        //4.flip():切换到读取数据的模式
        byteBuffer.flip();
        System.out.println("-----flip()-------");
        print(byteBuffer);
        //5.读取数据
        byte[] bytes = new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        System.out.println("读到的数据:" + new String(bytes));
        System.out.println("-----get()-------");
        print(byteBuffer);
        //6.rewind():重复读,使position归0
        byteBuffer.rewind();
        System.out.println("-----rewind()-------");
        print(byteBuffer);
        //7.clear():清空缓冲区,但是缓冲区中的数据依然存在,只是处于一种“被遗忘“的状态。只是不知道位置界限等,读取会有困难
        byteBuffer.clear();
        System.out.println("-----clear()-------");
        print(byteBuffer);
        //8.清理后仍然可以读取
        char aChar = byteBuffer.getChar();
        System.out.println("aChar=" + aChar);
        System.out.println("---清理后读取--getChar()-------");
        print(byteBuffer);
    }

    /**
     * 演示
     * mark:标记,表示记录当前position的位置,可以通过reset()恢复到mark的位置。
     */
    @Test
    public void test2() {
        ByteBuffer buffer = ByteBuffer.allocate(128);
        buffer.put("123".getBytes());
        System.out.println("-----put()--1-----");
        print(buffer);
        //标记位置
        buffer.mark();
        System.out.println("-----mark()-------");
        print(buffer);
        //继续放入
        buffer.put("456".getBytes());
        System.out.println("-----put()--2-----");
        print(buffer);
        //返回到标记处
        buffer.reset();
        System.out.println("-----reset()-------");
        print(buffer);


    }

    /**
     * 直接缓冲区与非直接缓冲区
     * 非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中。在每次调用基础操作系统的一个本机IO之前或者之后,虚拟机都会将缓冲区的内容复制到中间缓冲区(或者从中间缓冲区复制内容),缓冲区的内容驻留在JVM内,因此销毁容易,但是占用JVM内存开销,处理过程中有复制操作。
     * 非直接缓冲区的写入步骤:
     * 创建一个临时的ByteBuffer对象。
     * 将非直接缓冲区的内容复制到临时缓冲中。
     * 使用临时缓冲区执行低层次I/O操作。
     * 临时缓冲区对象离开作用域,并最终成为被回收的无用数据。
     * ————————————————
     * 直接缓冲区:通过allocateDirect()方法分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率。
     * 直接缓冲区在JVM内存外开辟内存,在每次调用基础操作系统的一个本机IO之前或者之后,虚拟机都会避免将缓冲区的内容复制到中间缓冲区(或者从中间缓冲区复制内容),缓冲区的内容驻留在物理内存内,会少一次复制过程,如果需要循环使用缓冲区,用直接缓冲区可以很大地提高性能。虽然直接缓冲区使JVM可以进行高效的I/O操作,但它使用的内存是操作系统分配的,绕过了JVM堆栈,建立和销毁比堆栈上的缓冲区要更大的开销
     * ————————————————
     */
    @Test
    public void test3() {
        //直接缓冲区
        ByteBuffer buffer = ByteBuffer.allocateDirect(128);
        System.out.println(buffer.isDirect());
        //非直接缓冲区
        ByteBuffer buffer2 = ByteBuffer.allocate(128);
        System.out.println(buffer2.isDirect());
    }

    /**
     * // Invariants: mark <= position <= limit <= capacity
     * private int mark = -1;
     * private int position = 0;
     * private int limit;
     * private int capacity;
     *
     * @param byteBuffer
     */
    public void print(ByteBuffer byteBuffer) {
        System.out.println("capacity=" + byteBuffer.capacity());
        System.out.println("limit=" + byteBuffer.limit());
        System.out.println("position=" + byteBuffer.position());
    }
}
View Code

相关文章:

  • 2021-11-29
  • 2022-12-23
  • 2021-04-04
  • 2021-12-15
  • 2022-01-01
  • 2021-11-08
  • 2022-12-23
猜你喜欢
  • 2021-12-01
  • 2022-01-05
  • 2021-12-13
  • 2021-09-11
  • 2021-06-10
  • 2021-05-29
  • 2021-12-21
相关资源
相似解决方案