NIO summary (a) of the NIO Buffer

Introduction: Why is there NIO?

We know very early JDK provides IO operations ----- BIO (synchronous blocking IO), then why should it provide NIO? Read some information in the future, I think the reason NIO appears mainly to solve the BIO unnecessary thread context switching.

Here we chat to explain:
We know that BIO is blocking IO, when the service terminated by a Socket connection, we need to open a thread to handle network requests this Socket connections (can not handle multiple single-threaded Socket requested). If the number of active online chat rooms are very many things (for example, there are one million users), we do want to open one million thread (able to open it?), As well as everyone in the chat room is not possible I've been chatting, right? If there are many users simply enter a chat room, but do nothing, then we give him a thread, they often switch to that thread, is not it a waste of resources (thread context switching is also the consumption of resources!), So use BIO server resource requirements are relatively high. To solve this problem, JDK 1.4 version of the bigwigs in the launch of the NIO. . . . .

Beginning in vain:

Java NIO consists of the following core components:

1 、Buffer

2、Channel

3、Selector

Traditional IO operations-oriented data stream from the stream reading means that each one or more bytes, until the completion of the data is not cached anywhere.

NIO buffer for operation, data is read from the buffer Channel Buffer to then process the data in the Buffer.

Buffer

Depending on the type, it provides the corresponding type of the buffer
Here Insert Picture Description
, but the ByteBuffer is commonly used, for all.

A buffer, an internal data store byte arrays, and maintaining several special variables for repeated use data.

Buffer four core properties

Here Insert Picture DescriptionHere Insert Picture Description
mark (): the current position assigned to the mark

public final Buffer mark() {
    mark = position;
    return this;
}
``

reset (): the value of the mark to the reduction position

public final Buffer reset() {
    int m = mark;
    if (m < 0)
        throw new InvalidMarkException();
    position = m;
    return this;
}

clear (): Once the data is read Buffer, Buffer need to be ready to be written again, clear the state will recover value, but does not erase data.

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

flip (): Buffer has two modes, write mode and read mode, the flip Buffer turned into read mode from the write mode.

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

rewind (): reset position is 0, the data read and write from scratch.

public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

Two core buffer access method of the data

  1. put (): data stored in the buffer
  2. get (): Gets the data buffer

NIO basic operations

Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

Direct and indirect buffer buffer

Here Insert Picture Description

Non-direct buffers

Here Insert Picture DescriptionCalling allocate () method to allocate a buffer, the buffer will be built on the JVM's memory

ByteBuffer implementation class "HeapByteBuffer" The allocate Code:

public static ByteBuffer allocate(int capacity) {
    if (capacity < 0)
        throw new IllegalArgumentException();
    return new HeapByteBuffer(capacity, capacity);
}
HeapByteBuffer(int cap, int lim) {  
    super(-1, 0, lim, cap, new byte[cap], 0);
}

HeapByteBuffer by initializing a byte array hd, heap memory space application in a virtual machine.

Direct buffers

Here Insert Picture Description
() Method of allocating buffer directly by allocateDirect, based on the physical memory buffers

ByteBuffer implementation class "DirectByteBuffer" of allocateDirect Code:

public static ByteBuffer allocateDirect(int capacity) {
    return new DirectByteBuffer(capacity);
}
DirectByteBuffer(int cap) {
    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 {
        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;
}

DirectByteBuffer unsafe.allocateMemory by applying external memory heap, and maintain the point at the address of the memory address of the variable ByteBuffer.

unsafe.setMemory (base, size, (byte) 0) a new method for the application of the data memory is cleared.

Published 45 original articles · won praise 3 · Views 2322

Guess you like

Origin blog.csdn.net/weixin_44046437/article/details/99628455