[Netty Learning Notes] II. NIO Core Component Buffer

In the previous section, we learned that the three core components of NIO are Buffer, Channel, Selector.

Relevance diagrams for the three core sections:

  1. Each channel corresponds to a Buffer
  2. Selector corresponds to one thread, and one thread corresponds to multiple channel s
  3. The figure above shows three channel s registered with selector
  4. Selector is event driven, and which channel the program switches to is perceived by the event
  5. Selector switches between channels at different times
  6. Buffer is a block of memory with an array at the bottom
  7. Data is read and written through Buffer(BIO is either an input stream or an output stream and cannot be bidirectional).Buffers can be read or written, and channel s are bidirectional.
Buffer Buffer

Buffer: Essentially a block of memory that can read and write data, which can be interpreted as a container object (with an array) that provides a set of methods for easily using the memory block. Buffer objects have built-in mechanisms to track and record buffer state changes.Channel provides access to data from files and networks, but data read or written must be Buffer-enabled.

In NIO, Buffer is a top-level parent class, it is an abstract class, and the common subclasses are as follows:

  1. ByteBuffer, storing byte data to buffer
  2. ShortBuffer, storing string data to buffer
  3. CharBuffer, stores character data to buffer
  4. IntBuffer, stores integer data to buffer
  5. LongBuffer stores long integer data to buffer
  6. DoubleBuffer stores decimals to buffers
  7. FloatBuffer stores decimals to buffers
  8. MappedByteBuffer Memory Mapping Buffer enables direct modification of data in out-of-heap memory

The Buffer class defines four properties that all buffers have to provide information about the data elements they contain:

attribute describe
capacity Capacity is the amount of large data that can be accommodated; set at buffer creation time and cannot be changed
limit Represents the current end point of a buffer, and cannot read or write where the buffer exceeds its limit; and the limit can be modified
position Location, the index of the next element to be read and written.This value is changed each time buffer data is read or written, in preparation for the next reading and writing
mark sign

The range that can be read is the element between position-limit s, otherwise data may not be read or errors may be reported

Buffer class related methods:

public final int capacity()//Returns the capacity of this buffer
public final int position()//Return the location of this buffer
public final Buffer position(int newPosition)//Set the location of this buffer
public final int limit()//Returns the limit of this buffer
public final Buffer limit(int newLimit)//Set the limit for this buffer
public final Buffer mark()//Set marker at the location of this buffer
public final Buffer reset()//Reset the position of this buffer to that of the previous marker
public final Buffer clear()//Clear the buffer to restore the markers to their original state, but the data is not actually erased; usually called before reading and writing data in a loop
public final Buffer flip() //Reverse this buffer by calling it when you have finished writing to read
public final Buffer rewind() //Rewind the buffer  
public final int remaining()//Returns the number of elements between the current position and the limit
public final boolean hasRemaining()//Tell if there is an element between the current position and the restriction
public abstract boolean isReadOnly()//Tell if this buffer is read-only
public abstract boolean hasArray()//Tell this buffer if it has an accessible underlying implementation array
public abstract Object array()//Returns the underlying implementation array of this buffer
public abstract int arrayOffset()//Returns the offset of the first buffer element in the implementation array at the bottom of this buffer
public abstract boolean isDirect()//Tell if this buffer is a direct buffer
ByteBuffer

The main methods of this class are as follows:

public static ByteBuffer allocateDirect(int capacity);//Create Direct Buffer
public static ByteBuffer allocate(int capacity);//Set the initial capacity of the buffer
public static ByteBuffer wrap(byte[] array);//Use an array in a buffer
public abstract byte get();//Get from current position, position will automatically + 1 after get
public abstract byte get();//get from Decision Location
public abstract ByteBuffer put(byte b);//Add from current position, position will automatically + 1 after put
public abstract ByteBuffer put(int index,byte b);//put from absolute position
Example
public class IntBufferDemo {
    public static void main(String[] args) {
        //Implement class HeapIntBuffer
        IntBuffer buffer = IntBuffer.allocate(5);
        buffer.put(1);
        buffer.put(2);
        buffer.put(3);
        buffer.put(4);
        buffer.put(5);

        //Write mode to read mode position/limit data change
        buffer.flip();

        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
    }
}

ByteBuffer supports typed put and get. If a put is of any data type, the get should be taken out using the corresponding data type. Otherwise, there may be a BufferUnderflowException exception with the following code:

public class ByteBufferDemo {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(40);
        //Double needs 8 bytes to store here If ByteBuffer space is less than 8 bytes BufferOverflowException is reported
        buffer.putDouble(0.1d);
        buffer.put((byte) 127);

        buffer.flip();

        /*
            ByteBuffer Supports typed put and get, what data type put into,
            get You should use the appropriate data type to extract it, otherwise there may be a BufferUnderflowException exception
         */
        System.out.println(buffer.getDouble());
        System.out.println(buffer.get());
    }
}
Buffer usage example

Demo1: Convert a regular Buffer to a read-only Buffer

public class ReadBufferDemo {
    public static void main(String[] args) {
        //The actual class is HeapByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(16);

        for (int i = 0; i < 16; i++) {
            buffer.put((byte) i);
        }

        buffer.flip();
        //Read-only buffers share current cache content, even if the current buffer content changes readOnlyBuffer synchronizes changes including pos/limit, etc.
        //The readOnlyBuffer implementation class is actually HeapByteBufferR
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();

        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }
        //Read-only buffer corresponding data changes when the original buffer changes
        buffer.put((byte) 16);

        readOnlyBuffer.flip();
        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }
        //Error here Read-only Buffer cannot be written
        readOnlyBuffer.put((byte) 17);

    }
}
87 original articles published. 21. 80,000 visits+
Private letter follow

Tags: Attribute less

Posted on Wed, 29 Jan 2020 18:24:45 -0800 by rami103