NIO's three major components and ByteBuffer

Table of contents

1. Three components of NIO

1、Channel

2、Buffer

3、Selector

Two, ByteBuffer

1. Basic use

2. Internal structure

3. Common methods

allocate method

read method

Convert between string and ByteBuffer

Scattering Reads

4. Read bag, half bag problem

3. File programming

1、FileChannel

2. Two Channels transmit data

3、Path

4、Files


1. Three components of NIO

non-blocking io non-blocking IO

1、Channel

Channel is the channel, here refers to the two-way channel of data, data can be read from the channel into the buffer, or the data of the buffer can be written into the channel, and the previous stream is either input or output, and the channel is lower than the stream

Common Channels are:

  • FileChannel: data transmission channel for files
  • DatagramChannel: UDP transmission data channel
  • SocketChannel: It is a data transmission channel when doing TCP (both client and server can be used)
  • ServerSocketChannel: It is the data transmission channel when doing TCP (dedicated server)

2、Buffer

Buffer is used to buffer read and write data. Common buffers are:

ByteBuffer (caching data in bytes) is an abstract class, and the implementation classes are:

  • MapperByteBuffer
  • DirectByteBuffer
  • HeapByteBuffer

3、Selector

A selector literally means a selector, and it needs to be combined with the design evolution of the server to understand its purpose

The server handles the communication of multiple clients. Each time one comes, a thread is created for the client to provide services for the client. If there are multiple threads, multiple threads are opened, and each thread manages a connection. When there are many connections, the No, because threads will take up memory, and each thread will take up memory. When there are 1,000 threads, it will be too large, and the memory will not be able to hold it. However, the number of CPU cores is limited, so the cost of thread context switching is high, which is only suitable for scenarios with a small number of connections .

Improve the thread pool to limit the number of threads, but this will make the socket work in blocking mode, because a thread has to manage multiple socket connections, only one can be processed at a time, and the rest will be blocked (the thread can only process one at a time socket, it cannot exit until the socket is disconnected, even if the socket has no read or write requests, it has to wait on it), so it is only suitable for short connection scenarios.

Two, ByteBuffer

1. Basic use

Initialize a buffer with a size of 10 bytes, and then read, write, and read in a loop. A channel is a channel for reading data. The data read each time is stored in the buffer, and then the API in the buffer is called to obtain the data.

ByteBuffer correct use posture:

  1. Write data to buffer, such as calling channel.read(buffer)
  2. Call flip() to switch to read mode
  3. Read data from buffer, for example call buffer.get()
  4. Call clear() or compact() to switch to write mode
  5. Repeat steps 1-4

2. Internal structure

ByteBuffer has the following important properties

  • capacity capacity
  • position read and write pointer, index subscript
  • limit read and write restrictions, how many bytes should be read and how many bytes should be written

In write mode, position is the writing position, and limit is equal to the capacity. The figure below shows the state after writing 4 bytes

After the filp action occurs, position switches to the read position, and limit switches to the read limit (the last position written)

After reading 4 bytes, the status

After the clear action occurs , the state switches from read mode to write mode

The compact method is to compress the part that has not been read forward , and then switch to the write mode

3. Common methods

allocate method

The ByteBuffer.allocate() method can pass in parameters to allocate memory for ByteBuffer. It is fixed and cannot be adjusted dynamically. If it exceeds this capacity, an error will be reported. Netty has enhanced byteBuffer to allow dynamic adjustment.

The allocate method is used to initialize Java’s heap memory (the read and write efficiency is low , and it will be affected by GC, and GC’s marking and copying may cause data copying), and the allocateDirect () method is used to initialize using direct memory ( The read and write efficiency is high , and there will be one less data copy; the efficiency of memory allocation is low, and improper use may cause memory leaks )

read method

rewind(): The data can be read repeatedly. Originally, the pointer is moved backward after reading once in order, but the source code of rewind will directly move the pointer to 0 and re-read. There are also mark and reset methods used in conjunction with rewind . mark will record the current position, and reset will reset the position to the position of mark. These two are enhancements for rewind.

Convert between string and ByteBuffer

String to ByteBuffer

The first is to manually convert it into binary form and put it in; the second is to use the encode method provided by charset , which provides many encoding formats, and it will automatically switch to the read mode after being put in ; the third is also the warp method provided by nio. Put it in, this will also switch to read mode 

ByteBuffer to string

After switching to the read mode, if it is the buffer transferred from the first mode, you need to add the flip method to switch the mode first, and then convert it with the decode method of charset. The returned result is a CharBuffer plus toString to convert it into a string

Scattering Reads

Scattered read data onetwothree, using the following method to read can fill data into multiple buffers

4. Read bag, half bag problem

Solution:

We write a method to receive messages, first switch to read mode, then loop through the delimiter to intercept the length of the message, and then store the message in the byteBuffer (loop from source to read to target to write).

3. File programming

1、FileChannel

FileChannel can only work in blocking mode

Obtain

FileChannel cannot be opened directly, and FileChannel must be obtained through FileInputStream, FileOutputStream or RandomAccessFile, all of which have getChannel method

  • The channel obtained through FileInputStream can only be read
  • The channel obtained through FileOutputStream can only be written
  • Whether you can read and write through RandomAccessFile depends on the read and write mode when constructing RandomAccessFile

read

It will read data from the channel and fill it into ByteBuffer. The return value indicates how many bytes have been read, and -1 indicates that the end of the file has been reached.

int readBytes = channel.read(buffer);

to write

Calling channel.write in while is because the write method cannot guarantee that all the contents of the buffer will be written to the channel at one time, so it is necessary to loop to determine whether there is any. 

closure

The channel must be closed, but calling the close method of FileInputStream will also indirectly call the close method of the channel

force write

For performance considerations, the operating system will cache the data, and when the final channel is closed, the data will be synchronized to the disk. Instead of writing to the disk immediately, you can call the force( true) method to write the file content and metadata to the disk immediately.

2. Two Channels transmit data

The transferTo method is to transfer the data of one channel to another channel. The first parameter is the starting position, the second parameter is the size of the transferred data, and the third parameter is the target position.

The efficiency of this method will be higher than that of output stream to write (optimized by zero copy at the bottom of the operating system)

The size of the transmitted data is limited to 2g, so we may not be able to transfer it all at once, so we need to improve it:

 In this way, data larger than 2g can be transmitted multiple times.

3、Path

jdk7 introduced the Path and Paths classes

  • Path is used to represent the file path
  • Paths is a tool class used to obtain Path instances

  •   . represents the current path
  •  .. represents the upper level path

4、Files

It is also a new class in 1.7, check whether the file exists

 

 

Guess you like

Origin blog.csdn.net/weixin_54232666/article/details/131464665