1. Basic concepts
IO is the process of copying data by main memory and external devices (hard disks, terminals, networks, etc.). IO is the underlying functional implementation of the operating system, which is completed through I/O instructions.
All language runtime systems provide high-level tools for performing I/O. (C's printfscanf, java's object-oriented encapsulation)
2. Review of Java Standard io
The Java standard IO class library is an abstraction of io object-oriented. Based on the underlying implementation of local methods, we do not need to pay attention to the underlying implementation. InputStream/OutputStream: Transfer one byte at a time. Reader/Writer: One character at a time.
3.nio introduction
nio is the abbreviation of javaNewIO, a new API provided in jdk1.4. The characteristics that Sun officially claims are as follows:
Provides (buffer) cache support for all primitive types.
Character set encoding and decoding solution.
Channel: A new original I/O abstraction.
Supports file access interfaces for lock and memory mapped files.
Provides non-bloking, non-blocking, highly scalable network I/O.
This article will learn and introduce these features.
4.Buffer&Chanel
Channel and buffer are NIO and are the two most basic data type abstractions.
Buffer:
It is a continuous block of memory.
It is the transit place for reading or writing of NIO data.
Channel:
The source of data or destination of data
A unique interface for providing data to buffers or reading buffer data, buffer objects.
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";// Get input and output streams of source and target files FileInputStream fin = new FileInputStream(infile);FileOutputStream fout = new FileOutputStream(outfile);// Get input and output channels FileChannel fcin = fin.getChannel();FileChannel fcout = fout.getChannel();// Create a buffer ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) {// Clear method resets the buffer so that it can accept read data buffer.clear();// Read data from the input channel to the buffer int r = fcin.read(buffer);// read method returns the number of bytes read, which may be zero, if the channel has reached the end of the stream, returns -1 if (r == -1) {break;}// flip method allows the buffer to write newly 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 following figure is copied from the information):
Figure 2: Buffer internal structure
A buffer mainly controls the reading and writing process by three variables position, limit, and capacity. The meaning of these three variables is shown in the following table:
parameter | Writing mode | Reading mode |
position | The number of unit data currently written. | The current unit data location read. |
limit | It represents the maximum number of units of data and capacity that can be written is the same. | It represents the maximum number of units of data that can be read, which is consistent with the amount of unit data written before. |
capacity | Buffer capacity | Buffer capacity |
Common Buffer methods:
flip(): Convert write mode to read mode
rewind(): reset position to 0, generally used for repeated reading.
clear(): Clear the buffer and prepare to be written again (position becomes 0, limit becomes capacity).
compact(): Copy unread data to the head of the buffer.
mark(), reset(): mark can mark a position, reset can be reset to this position.
Common types of Buffer: ByteBuffer, MappedByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer.
Common channels: FileChannel, DatagramChannel (UDP), SocketChannel (TCP), ServerSocketChannel (TCP)
A simple performance test was performed on this machine. My laptop performs in moderation. (See the attachment for the specific code. See the example below in the nio.sample.filecopy package) The following is the reference data:
Scenario 1: Copy a 370M file
Scenario 2: Three threads copy at the same time, each thread copies a 370M file.
Scene | FileInputStream+ FileOutputStream | FileInputStream+ BufferedInputStream+ FileOutputStream | ByteBuffer+ FileChannel | MappedByteBuffer +FileChannel |
Scene for a time (milliseconds) | 25155 | 17500 | 19000 | 16500 |
Scene 2 time (milliseconds) | 69000 | 67031 | 74031 | 71016 |
5.nio.charset
Character encoding and decoding: bytecode itself is just some numbers, which are correctly parsed in the correct context. When storing data into ByteBuffer, you need to consider the encoding method of the character set. When reading and displaying ByteBuffer data, you involve decoding the character set.
Java.nio.charset provides a set of solutions for encoding and decoding.
Taking our most common http request as an example, the request must be coded correctly when requesting. The response must be correctly decoded when it is obtained.
The following code sends a request to baidu and gets the results for display. The example demonstrates the use of charset.
Example 2BaiduReader.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 the connection channel = SocketChannel.open(socketAddress);//step2: Send the request, encode channel.write(charset.encode("GET " + "/ HTTP/1.1" + "/r/n/r/n"));//step3: Read the data ByteBuffer buffer = ByteBuffer.allocate(1024);// Create a 1024-byte buffer while (channel.read(buffer) != -1) {buffer.flip();// The flip method is called before the buffer byte operation. System.out.println(charset.decode(buffer));// Use Charset.decode method to convert bytes to string buffer.clear();// Clear 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
Regarding non-blocking IO, we will understand from the aspects of what is blocking, what is non-blocking, the non-blocking principle and the asynchronous core API.
What is blockage?
A common network IO communication process is as follows:
From this network communication process, let’s understand what blocking is:
If the connection has not arrived in the above process, then accept will block, the program will have to hang after running here, and the CPU will instead execute other threads.
If the data is not ready in the above process, the read will also block.
Features of blocking network IO: Multi-threading multiple connections. Each thread has its own stack space and takes up some CPU time. Every thread will block when it encounters an external ready. The result of blocking is that it will lead to a large number of process context switching. And most process context switching may be meaningless. For example, suppose a thread listens for a port, and there will only be a few requests in a day, but the CPU has to constantly make context switching attempts for the thread, and most of the switching ends in blocking.
What is non-blocking?
Here is a metaphor:
On a bus from A to B, there are many points on the road that may get off. The driver doesn’t know which points will get off the bus. How to deal with those who need to get off the bus better?
1. During the process, the driver regularly asks each passenger whether he has arrived at the destination. If someone says that, the driver stops and the passenger gets off. (Similar to blocking)
2. Everyone tells the ticket seller their destination and then sleeps. The driver only interacts with the ticket seller. When he arrives at a certain point, the ticket seller will notify the passenger to get off the bus. (Similar to non-blocking)
Obviously, everyone to reach a destination can be considered a thread, and the driver can be considered a CPU. In the blocking style, each thread needs to constantly poll and switch context to achieve the result of finding the destination. In the non-blocking mode, every passenger (thread) is sleeping (sleeping) and only wakes up when the real external environment is ready. Such wakeup will definitely not block.
The principle of non-blocking
Switch the entire process to small tasks and complete it through collaboration between tasks.
A dedicated thread handles all IO events and is responsible for distribution.
Event-driven mechanism: triggers when an event arrives, rather than monitoring events simultaneously.
Thread communication: threads communicate through wait, notify and other means. Ensure that every context switch makes sense. Reduce unnecessary process switching.
The following is the structure of asynchronous IO:
Reactor is the above metaphorical role of the ticket seller. The processing flow of each thread is probably 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 and distribute events.
Use a select thread to listen to events on multiple channels and trigger corresponding responses based on event drivers. There is no need to allocate a thread for each channel.
SelectionKey
Contains the binding of the channel corresponding to the status information of the event and the time.
Summarize
The above is the entire content of this article about basic Java knowledge essays, I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!