English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
1.Basic concepts
IO is the process of copying data between main memory and external devices (hard drives, terminals, and networks, etc.). IO is the implementation of the underlying functionality of the operating system, and the bottom layer uses I/O instructions to complete.
All language runtime systems provide execution of I/O higher-level tools. (C's printfscanf, Java's object-oriented encapsulation)
2.Java standard io review
The Java standard IO class library is an object-oriented abstraction for IO. Based on the underlying implementation of local methods, we need not pay attention to the underlying implementation. InputStream\OutputStream (byte stream): Transfer one byte at a time. Reader\Writer (character stream): Transfer one character at a time.
3.nio introduction
nio is the abbreviation of javaNewIO, in jdk1.4The new api provided in it. The features Sun officially boasts are as follows:
–Provide (Buffer) cache support for all primitive types.
–Character set encoding and decoding solution.
–Channel: A new original I/O abstraction.
–Support lock and memory-mapped file file access interface.
–Provide multi-threaded (non-blocking) I/O-Non-blocking high scalability network I/O.
This article will focus on these features for learning and introduction.
4.Buffer&Chanel
Channel and buffer are two basic data type abstractions in NIO.
Buffer:
–Is a continuous memory block.
–Is the intermediate transfer point for NIO data read or write.
Channel:
–The source or destination of data
–The only interface for providing data to or reading data from the buffer, the unique interface of the buffer object.
–Asynchronous I/O support
Example 1:CopyFile.java:
package sample; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class CopyFile { public static void main(String[] args) throws Exception { String infile = "C:\\copy.sql"; String outfile = "C:\\copy.txt"; // Obtain input and output streams of the source and target files FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); // Obtain input and output channels FileChannel fcin = fin.getChannel(); FileChannel fcout = fout.getChannel(); // Create a buffer ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { // The clear method resets the buffer, making it ready to accept read data buffer.clear(); // Read data from the input channel to the buffer int r = fcin.read(buffer); // The read method returns the number of bytes read, which may be zero. If the channel has reached the end of the stream, it returns-1 if (r == -1) { break; } // The flip method allows the buffer to write new read data to another channel buffer.flip(); // Write data from the output channel to the buffer fcout.write(buffer); } } }
The internal structure of the buffer is as follows (the figure below is copied from the material):
Figure2: buffer internal structure
A buffer is mainly controlled by the three variables position, limit, and capacity in the process of reading and writing. The meanings of these three variables are shown in the following table:
Parameters |
Write mode |
Read mode |
position |
The current number of units of data written. |
The current position of the unit of data to be read. |
limit |
Represents the maximum number of units of data that can be written, which is the same as the capacity. |
Represents the maximum number of units of data that can be read, consistent with the amount of data written previously. |
capacity |
buffer capacity |
buffer capacity |
Common methods of Buffer:
flip(): Convert write mode to read mode
rewind(): Reset position to 0, generally used for repeated reading.
clear(): Clear the buffer, ready for writing again (position becomes 0, limit becomes capacity).
compact(): Copy the unread data to the head of the buffer.
mark() and reset(): mark can mark a position, and reset can reset to that position.
Common types of buffers: ByteBuffer, MappedByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer.
Common types of channels: FileChannel, DatagramChannel (UDP), SocketChannel (TCP), ServerSocketChannel (TCP)
A simple performance test was conducted on this machine. The performance of my laptop is general. (The specific code can be found in the attachment. See the examples under the nio.sample.filecopy package.) The following are reference data:
–Scenario1:Copy one370M file
–Scenario2: Three threads copy simultaneously, each thread copies one370M file
Scenario |
FileInputStream+ FileOutputStream |
FileInputStream+ BufferedInputStream+ FileOutputStream |
ByteBuffer+ FileChannel |
MappedByteBuffer +FileChannel |
Scenario 1 time (milliseconds) |
25155 |
17500 |
19000 |
16500 |
Scenario 2 time (milliseconds) |
69000 |
67031 |
74031 |
71016 |
5.nio.charset
Character encoding and decoding: byte code itself is just some numbers, which are correctly parsed when placed in the correct context. When storing data in ByteBuffer, the encoding method of the character set needs to be considered, and character set decoding is involved when reading and displaying ByteBuffer data.
Java.nio.charset provides a set of solutions for encoding and decoding.
Taking the most common HTTP request as an example, proper encoding must be used when sending the request. Proper decoding must be performed when receiving the response.
The following code sends a request to baidu and retrieves the result for display. This example demonstrates the use of charset.
Example2BaiduReader.java
package nio.readpage; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.net.InetSocketAddress; import java.io.IOException; public class BaiduReader { private Charset charset = Charset.forName("GBK"); // Create GBK character set private SocketChannel channel; public void readHTMLContent() { try { InetSocketAddress socketAddress = new InetSocketAddress( "www.baidu.com", 80); //step1: Open connection channel = SocketChannel.open(socketAddress); //step2: Send request using GBK encoding channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n")); //step3:Read data ByteBuffer buffer = ByteBuffer.allocate(1024); // Create1024Byte buffer while (channel.read(buffer) != -1) { buffer.flip(); // The flip method is called before the byte operation in the read buffer. System.out.println(charset.decode(buffer)); // Use the Charset.decode method to convert bytes to a string buffer.clear(); // Clear the buffer } } catch (IOException e) { System.err.println(e.toString()); } finally { if (channel != null) { try { channel.close(); } catch (IOException e) { } } } } public static void main(String[] args) { new BaiduReader().readHTMLContent(); } }
6.Non-blocking IO
We will understand non-blocking IO from several aspects: what is blocking, what is non-blocking, the principle of non-blocking, and asynchronous core API.
What is blocking?
A common network IO communication process is as follows:
Let's understand what blocking means from the perspective of this network communication process:
If the connection has not arrived in the above process, then the accept operation will block, and the program will have to hang here, with the CPU turning to execute other threads.
If the data is not ready in the above process, the read operation will also block.
Characteristics of blocking network IO: multi-threaded processing of multiple connections. Each thread has its own stack space and consumes some CPU time. When each thread encounters an external event that is not ready, it will block. The result of blocking is that it brings a large number of process context switches. And most of these context switches may be meaningless. For example, if a thread is listening on a port, there may only be a few requests coming in a day, but the CPU has to keep making context switch attempts for this thread, and most of these switches end in blocking.
What is non-blocking?
Here is a metaphor:
On a public bus traveling from A to B, there are many points where passengers might get off. The driver does not know which points and which passengers will get off. How should the driver handle those who need to get off?
1During the journey, the driver asks each passenger whether they have reached their destination. If someone says they have, the driver stops the bus, and the passengers get off. (Similar to blocking)
2Each person tells the ticket collector their destination and then falls asleep. The driver only interacts with the ticket collector, and at a certain point, the ticket collector notifies the passengers to get off the bus. (Similar to non-blocking)
It is obvious that everyone's arrival at a destination can be considered a thread, and the driver can be considered as the CPU. In blocking, each thread needs to poll continuously, switch contexts, to achieve the result of finding the destination. In non-blocking, each passenger (thread) is sleeping (sleeping), and only wakes up when the external environment is truly ready, and this awakening will not block.
The principle of non-blocking
Switch the whole process into small tasks and complete through collaboration between tasks.
A dedicated thread handles all IO events and is responsible for distribution.
Event-driven mechanism: Trigger when the event arrives, rather than synchronously monitoring the event.
Thread communication: Threads communicate with each other through wait, notify, and other methods to ensure that each context switch is meaningful and to reduce unnecessary process switching.
The following is the structure of asynchronous IO:
Reactor is the metaphorical role of the ticket seller. The processing flow of each thread is roughly to read data, decode, calculate processing, encode, and send responses.
Asynchronous IO Core API
Selector
The core class of asynchronous IO, which can detect events on one or more channels (channel) and distribute them accordingly.
A single select thread can listen to events on multiple channels and trigger the corresponding response based on event-driven, without the need to allocate a thread for each channel.
SelectionKey
Contains the state information of events and the binding of channels corresponding to the time.
Summary
That's all about the basic knowledge of Java articles in this article. I hope it will be helpful to everyone. Those who are interested can continue to read other related topics on this site. Welcome to leave a message to point out any shortcomings. Thank you friends for your support of this site!
Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting. Provide relevant evidence, and once verified, this site will immediately delete the content suspected of infringement.)