重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

深入浅出javanio-创新互联

Buffer

翻译为缓冲,是一块可以读写的区域。

专业网站设计公司,专做排名好的好网站,排在同行前面,为您带来客户和效益!成都创新互联公司为您提供品质好成都网站建设,五站合一网站设计制作,服务好的网站设计公司,负责任的成都网站制作公司!为什么需要缓冲?

思考:没有buffer之前的读写。

方法

抽象方法

//是否只读
    public abstract boolean isReadOnly();
	//判断有没有数组
    public abstract boolean hasArray();
	//返回数组
    public abstract Object array();
    //返回数组偏移
    public abstract int arrayOffset();
	//是否是直接缓冲区
    public abstract boolean isDirect();
    //切分
    public abstract Buffer slice();
    //切分
    public abstract Buffer slice(int index, int length);
	//复制一个buffer
    public abstract Buffer duplicate();
    //
    abstract Object base();   

构造函数

Buffer(long addr, int cap, MemorySegmentProxy segment) {this.address = addr;
        this.capacity = cap;
        this.segment = segment;
    }
    
    Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) {   // package-private
        if (cap< 0)
            throw createCapacityException(cap);
        this.capacity = cap;
        this.segment = segment;
        limit(lim);
        position(pos);
        if (mark >= 0) {if (mark >pos)
                throw new IllegalArgumentException("mark >position: ("
                                                   + mark + ">" + pos + ")");
            this.mark = mark;
        }
    }

普通方法

在这里插入代码片

字段

static final Unsafe UNSAFE = Unsafe.getUnsafe();
    
    static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();

    static final int SPLITERATOR_CHARACTERISTICS =
        Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;

    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;
    
    long address;
    
    // Used by buffers generated by the memory access API (JEP-370)
    final MemorySegmentProxy segment;
子类

在这里插入图片描述
常见类型的缓冲

ByteBuffer

在这里插入图片描述

public abstract class ByteBuffer
    extends Buffer
    implements Comparable{}

ByteBuffer是抽象类无法直接实例化,可以通过allocate等方法返回实例。

allocate

public static ByteBuffer allocate(int capacity) {if (capacity< 0)
            throw new IllegalArgumentException();
        return new HeapByteBuffer(capacity, capacity);
    }

allocateDirect

public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);
    }

ByteBuffer 分为HeapByteBuffer和DirectByteBuffer两种,翻译成人话就是堆字节缓冲和直接字节缓冲,第二种不受 JVM 控制。

ByteBuffer hbb = ByteBuffer.allocate(1024);
        ByteBuffer dbb = ByteBuffer.allocateDirect(1024);

在后面的介绍中,hbb代指 JVM 缓冲区,dbb代指直接缓冲区。

HeapByteBuffer DirectByteBuffer 常见方法 allocate

下面对 allocate 的调用链路参数进行分析。

public static ByteBuffer allocate(int capacity) {if (capacity< 0)
            throw new IllegalArgumentException();
        //capacity >= 0
        return new HeapByteBuffer(capacity, capacity);
    }

cap = lim = capacity,由 HeapByteBuffer 构造函数调用 super

HeapByteBuffer(int cap, int lim) {   
        super(-1, 0, lim, cap, new byte[cap], 0);
    }

mark = -1
pos = 0
lim = cap
cap = cap
hb = new byte[cap]
offset = 0

ByteBuffer(int mark, int pos, int lim, int cap,  
                 byte[] hb, int offset)
    {super(mark, pos, lim, cap); //-1,0,cap,cap
        this.hb = hb; //new byte[cap]
        this.offset = offset; //0
    }

hb字节数组和offset 偏移量为 ByteBuffer 字段。

mark = -1
pos = 0
lim = cap
cap = cap

Buffer(int mark, int pos, int lim, int cap) {	//判断多余 cap >0     
        if (cap< 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);  
        this.capacity = cap; // 1
        limit(lim); //2
        position(pos); //3 
        //汇总分析的参数 mark = -1,pos = 0
        if (mark >= 0) {if (mark >pos)
                throw new IllegalArgumentException("mark >position: ("
                                                   + mark + ">" + pos + ")");
            this.mark = mark;
        }
    }

核心代码表示为1,2,3的部分。

public final Buffer limit(int newLimit) {// newLimit = lim = cap
        if ((newLimit >capacity) || (newLimit< 0))
            throw new IllegalArgumentException();
        limit = newLimit; //limit = newLimit = lim = cap
        if (position >limit) position = limit; // position = 0 limit = cap
        if (mark >limit) mark = -1; // mark = -1
        return this;
    }
public final Buffer position(int newPosition) {// newPosition = pos = pos = 0
        if ((newPosition >limit) || (newPosition< 0))
            throw new IllegalArgumentException();
        position = newPosition; // position =  newPosition = pos = pos = 0
        if (mark >position) mark = -1;
        return this;
    }

所以经过这一串构造函数后,buffer中的值分别为

java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]

pos = 位置,lim = 限制,cap = 容量,大值。

allocateDirect
public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);
    }
DirectByteBuffer(int cap) {//cap =  capacity
    	//调用链路
        super(-1, 0, cap, cap);
       	//
        boolean pa = VM.isDirectMemoryPageAligned();
        int ps = Bits.pageSize();
        long size = Math.max(1L, (long)cap + (pa ? ps : 0));
        Bits.reserveMemory(size, cap);

        long base = 0;
        try {	//unsafe 分配内存空间
            base = unsafe.allocateMemory(size);
        } catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);
            throw x;
        }
        unsafe.setMemory(base, size, (byte) 0);
        if (pa && (base % ps != 0)) {// Round up to page boundary
            address = base + ps - (base & (ps - 1));
        } else {address = base;
        }
        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
        att = null;
    }
MappedByteBuffer(int mark, int pos, int lim, int cap) {// package-private
        super(mark, pos, lim, cap);
        this.fd = null;
    }
ByteBuffer(int mark, int pos, int lim, int cap) {// package-private
        this(mark, pos, lim, cap, null, 0);
    }
ByteBuffer(int mark, int pos, int lim, int cap,   // package-private
                 byte[] hb, int offset)
    {super(mark, pos, lim, cap);
        this.hb = hb;
        this.offset = offset;
    }
Buffer(int mark, int pos, int lim, int cap) {   // package-private
        if (cap< 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        this.capacity = cap;
        limit(lim);
        position(pos);
        if (mark >= 0) {if (mark >pos)
                throw new IllegalArgumentException("mark >position: ("
                                                   + mark + ">" + pos + ")");
            this.mark = mark;
        }
    }

调用过程不再赘述,跟 allocate 链路差不多,区别是使用 unsafe 进行内存分配和其他的操作。

flip 翻转
public final Buffer flip() {limit = position;
        position = 0;
        mark = -1;
        return this;
    }

案例

ByteBuffer hbb = ByteBuffer.allocate(1024);
        System.out.println(hbb.toString());
        hbb.flip();
        System.out.println(hbb.toString());

输出

java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=0 cap=1024]
hasRemaining 是否有剩余
public final boolean hasRemaining() {return position< limit;
    }

position< limit 代表有剩余,position = limit 代表空间已经满了

clear 清除
public final Buffer clear() {position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

将buffer三个指针位置重置。

get

hbb

final byte[] hb;    

    public byte get() {return hb[ix(nextGetIndex())];
    }

dbb

public byte get() {return ((unsafe.getByte(ix(nextGetIndex()))));
    }
asReadOnlyBuffer 只读buffer
public ByteBuffer asReadOnlyBuffer() {return new HeapByteBufferR(hb, this.markValue(), this.position(), this.limit(),
         this.capacity(), offset);
 }
buffer 案例1 基本操作读和写

创建5个容量的buffer,依次将i放进去,翻转buf,依次读出来。

public class byteBuffer02 {public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(5);
        for (byte i = 0; i< buffer.capacity(); i++) {buffer.put(i);

        }
        buffer.flip();
        while (buffer.hasRemaining()) {System.out.println(buffer.get());
        }
    }
}
buffer 案例2 不同类型数据读写
public class ByteBuffer03 {public static void main(String[] args) {ByteBuffer bb = ByteBuffer.allocate(64);
        bb.putInt(100);
        bb.putLong(9);
        bb.putChar('a');
        bb.putShort((short) 4);
        bb.flip();
        System.out.println("----");
        System.out.println(bb.getInt());
        System.out.println(bb.getLong());
        System.out.println(bb.getChar());
        System.out.println(bb.getShort());
    }
}
buffer 案例3 只读 buffer
public class ByteBuffer04 {public static void main(String[] args) {ByteBuffer b1 = ByteBuffer.allocate(64);
        ByteBuffer b2 = b1.asReadOnlyBuffer();
        b1.putInt(5);
        b2.putInt(5);
    }
}
MappedByteBuffer

深入浅出java.nio.MappedByteBuffer

Channel 通道

实现
在这里插入图片描述
源码

public interface Channel extends Closeable {//是否开启
    public boolean isOpen();
    //关闭
    public void close() throws IOException;

}
FileChannel 开启通道的几种方式
static File file = new File("D://a.txt");
从 RandomAccessFile 中getChannel
RandomAccessFile raf = new RandomAccessFile(file, "rw");
        FileChannel fc = raf.getChannel();
从 stream 中 getChannel
FileOutputStream fos = new FileOutputStream(file);
        FileChannel fc2 = fos.getChannel();      
FileChannel.open
FileChannel fc3 = FileChannel.open(null, null);
案例1

将 uuid 读出来

public class ReadFileUid {static File file = new File("D://a.txt");

    public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);
        try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
             FileChannel fc = raf.getChannel()) {int read = fc.read(bf);
            System.out.println(read);
            System.out.println(bf);
            bf.flip();
            System.out.println(bf);
            byte[] bytes = new byte[bf.limit()];
            bf.get(bytes);
            System.out.println(bf);
            System.out.println(Arrays.toString(bytes));
            String str = new String(bytes, StandardCharsets.UTF_8);
            System.out.println(str);
        }
    }
}

输出

36
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=36 cap=1024]
[54, 51, 51, 53, 98, 102, 53, 97, 45,
99, 57, 100, 54, 45, 52, 53, 51, 99,
45, 98, 57, 99, 98, 45, 102, 50, 52,
102, 56, 97, 54, 101, 98, 50, 99, 50]
6335bf5a-c9d6-453c-b9cb-f24f8a6eb2c2
案例2

将 uuid 写到文件中

public class WriteFileUid {static File file = new File("D://a.txt");

    public static void main(String[] args) throws Exception {ByteBuffer bf = ByteBuffer.allocate(1024);
        try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
             FileChannel fc = raf.getChannel()) {String uuid = UUID.randomUUID().toString();
            System.out.println(uuid);
            byte[] bytes = uuid.getBytes(StandardCharsets.UTF_8);
            System.out.println(Arrays.toString(bytes));
            System.out.println(bf);
            bf.put(bytes);
            System.out.println(bf);
            bf.flip();
            System.out.println(bf);
            int write = fc.write(bf);
            System.out.println(write);
        }
    }
}
efdd8059-4f47-42e9-b9f9-aadd4a324309
[101, 102, 100, 100, 56, 48, 53, 57, 45, 52, 102, 52, 55,
 45, 52, 50, 101, 57, 45, 98, 57, 102, 57, 45, 97, 97,
  100, 100, 52, 97, 51, 50, 52, 51, 48, 57]
java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=36 lim=1024 cap=1024]
java.nio.HeapByteBuffer[pos=0 lim=36 cap=1024]
36

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前标题:深入浅出javanio-创新互联
文章出自:http://cqcxhl.com/article/dgpsgc.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP