Table of contents
Convert between string and ByteBuffer
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:
- Write data to buffer, such as calling channel.read(buffer)
- Call flip() to switch to read mode
- Read data from buffer, for example call buffer.get()
- Call clear() or compact() to switch to write mode
- 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