Advantages and disadvantages of blocking and non-blocking Io packages in Java
The cornerstone behind NiO design: the reactor model, which is used for event Multi-Channel Separation and dispatching of the architecture model.
Reactor: an architecture pattern used for event Multi-Channel Separation and allocation
Generally, a file or device specified by a file descriptor can work in two ways: blocking and non-blocking. Blocking means that when you try to read and write the file descriptor, the program enters the waiting state if there is nothing to read at the time or it cannot be written at the moment, until something is readable or writable. For non-blocking states, if nothing is readable or not writable, the read/write function returns immediately without waiting.
A common practice is: each time a socket connection is established, a new thread is created to communicate with the socket separately (through blocking ). This method has a high response speed and is easy to control. It is very effective when the number of connections is small, however, generating a thread for each connection is undoubtedly a waste of system resources. If there are many connections, there will be insufficient resources.
Another efficient method is to store a socket connection list on the server side and round-robin the list. If data is readable on a socket port (read-only ), the corresponding read operation of the socket connection is called. If a socket port is found to be writable (write-ready), the corresponding write operation of the socket connection is called; if the socket connection of a port has been interrupted, call the corresponding destructor to close the port. This greatly improves the efficiency of fully utilizing server resources.
In the traditional blocking Io mode, each connection must be handled by a thread, and the thread cannot exit.
Non-blocking I/O. Because it is based on the reactor mode, it is used in the architecture mode of event Multi-Channel Separation and allocation, so it can be processed by the thread pool. When the event comes, it is processed, and the thread is returned after processing. The traditional blocking method cannot use a thread pool for processing. If there are currently 10000 connections, the non-blocking method may be done with a thread pool of 1000 threads, the traditional blocking method requires 10000 requests. If the number of connections is large, there will be insufficient resources. The core advantage of non-blocking is here.
Why is this happening? We will analyze them in detail below:
First, let's analyze the bottleneck of traditional blocking Io. When the number of connections is small, traditional I/O writing is easy to use. However, as the number of connections increases, traditional I/O problems will not work. As mentioned above, the traditional Io processing consumes one thread for each connection, and the program efficiency increases with the increase of the number of threads when the number of threads is small, but after a certain number, is reduced with the increase in the number of threads. Here we come to the conclusion that the bottleneck of traditional blocking Io is that it cannot process too many connections.
Then, the purpose of non-blocking Io is to solve this bottleneck. How is non-blocking I/O implemented? The number of threads for non-blocking Io processing connections is not linked to the number of connections. That is to say, 10000 threads are not required to process 10000 non-blocking Io connections, you can use 1000 or 2000 threads for processing. Because non-blocking Io processing connections are asynchronous. When a connection sends a request to the server, the server treats the connection request as a request "Event" and assigns this "Event" to the corresponding function for processing. We can put this processing function in the thread for execution, and return the thread after execution. In this way, a thread can process multiple events asynchronously. Most of the time for blocking I/O threads is wasted waiting for requests.
[B] referenced from: http://javag.javaeye.com
Blocking Io is a method called during read/write, such as the read () or write () method.
Wait until the method is executed. The so-called blocking Io stream is to block the current thread when reading and writing data from the data stream until the IO stream can be used again. You can also use the avaliablebytes () of the stream () function to check the number of bytes in the current stream that can be read, so that it will not be blocked.
Java code
Import java. Io. ioexception;
Import java. Io. inputstream;
Import java. NiO. bytebuffer;
Import java. NiO. channels. readablebytechannel;
Public class ChannelInputStream extends InputStream {
Private ReadableByteChannel;
Public ChannelInputStream (ReadableByteChannel channel) throws IllegalArgumentException {
If (channel = null ){
Throw new IllegalArgumentException ("The readable byte channel is null ");
}
This. channel = channel;
}
Public int read () throws ioexception {
Bytebuffer buffer = bytebuffer. Allocate (1 );
Int result = channel. Read (buffer );
If (result! =-1 ){
Buffer. Flip ();
Result = (INT) buffer. Get ();
Buffer. Clear ();
}
Return result;
}
Public int read (byte B []) throws ioexception {
Bytebuffer buffer = bytebuffer. Allocate (B. Length );
Int result = channel. read (buffer );
If (result! =-1 ){
Buffer. flip ();
Buffer. get (B, 0, result );
Buffer. clear ();
}
Return result;
}
Public int read (byte B [], int off, int len) throws IOException {
ByteBuffer buffer = ByteBuffer. allocate (B. length );
Int result = channel. read (buffer );
If (result! =-1 ){
Buffer. Flip ();
Buffer. Get (B, off, Len> result? Result: Len );
Buffer. Clear ();
}
Return result;
}
Public void close () throws ioexception {
Channel. Close ();
}
}
Advantages and disadvantages of blocking and non-blocking Io packages in Java
The cornerstone behind NiO design: the reactor model, which is used for event Multi-Channel Separation and dispatching of the architecture model.
Reactor: an architecture pattern used for event Multi-Channel Separation and allocation
Generally, a file or device specified by a file descriptor can work in two ways: blocking and non-blocking. Blocking means that when you try to read and write the file descriptor, the program enters the waiting state if there is nothing to read at the time or it cannot be written at the moment, until something is readable or writable. For non-blocking states, if nothing is readable or not writable, the read/write function returns immediately without waiting.
A common practice is: each time a socket connection is established, a new thread is created to communicate with the socket separately (through blocking ). This method has a high response speed and is easy to control. It is very effective when the number of connections is small, however, generating a thread for each connection is undoubtedly a waste of system resources. If there are many connections, there will be insufficient resources.
Another efficient method is to store a socket connection list on the server side and round-robin the list. If data is readable on a socket port (read-only ), the corresponding read operation of the socket connection is called. If a socket port is found to be writable (write-ready), the corresponding write operation of the socket connection is called; if the socket connection of a port has been interrupted, call the corresponding destructor to close the port. This greatly improves the efficiency of fully utilizing server resources.
In the traditional blocking Io mode, each connection must be handled by a thread, and the thread cannot exit.
Non-blocking I/O. Because it is based on the reactor mode, it is used in the architecture mode of event Multi-Channel Separation and allocation, so it can be processed by the thread pool. When the event comes, it is processed, and the thread is returned after processing. The traditional blocking method cannot use a thread pool for processing. If there are currently 10000 connections, the non-blocking method may be done with a thread pool of 1000 threads, the traditional blocking method requires 10000 requests. If the number of connections is large, there will be insufficient resources. The core advantage of non-blocking is here.
Why is this happening? We will analyze them in detail below:
First, let's analyze the bottleneck of traditional blocking IO. When the number of connections is small, traditional I/O writing is easy to use. However, as the number of connections increases, traditional I/O problems will not work. As mentioned above, the traditional IO processing consumes one thread for each connection, and the program efficiency increases with the increase of the number of threads when the number of threads is small, but after a certain number, is reduced with the increase in the number of threads. Here we come to the conclusion that the bottleneck of traditional blocking IO is that it cannot process too many connections.
Then, the purpose of non-blocking IO is to solve this bottleneck. How is non-blocking I/O implemented? The number of threads for non-blocking IO processing connections is not linked to the number of connections. That is to say, 10000 threads are not required to process 10000 non-blocking IO connections, you can use 1000 or 2000 threads for processing. Because non-blocking IO processing connections are asynchronous. When a connection sends a request to the server, the server treats the connection request as a request "Event" and assigns this "Event" to the corresponding function for processing. We can put this processing function in the thread for execution, and return the thread after execution. In this way, a thread can process multiple events asynchronously. Most of the time for blocking I/O threads is wasted waiting for requests.
[B] referenced from: http://javag.javaeye.com
Blocking IO is a method called during read/write, such as the read () or write () method.
Wait until the method is executed. The so-called blocking IO stream is to block the current thread when reading and writing data from the data stream until the IO stream can be used again. You can also use the avaliableBytes () of the stream () function to check the number of bytes in the current stream that can be read, so that it will not be blocked.
Java code
Import java. io. IOException;
Import java. io. InputStream;
Import java. nio. ByteBuffer;
Import java. nio. channels. ReadableByteChannel;
Public class channelinputstream extends inputstream {
Private readablebytechannel;
Public channelinputstream (readablebytechannel channel) throws illegalargumentexception {
If (Channel = NULL ){
Throw new IllegalArgumentException ("The readable byte channel is null ");
}
This. channel = channel;
}
Public int read () throws IOException {
ByteBuffer buffer = ByteBuffer. allocate (1 );
Int result = channel. read (buffer );
If (result! =-1 ){
Buffer. flip ();
Result = (int) buffer. get ();
Buffer. clear ();
}
Return result;
}
Public int read (byte B []) throws IOException {
ByteBuffer buffer = ByteBuffer. allocate (B. length );
Int result = channel. read (buffer );
If (result! =-1 ){
Buffer. flip ();
Buffer. get (B, 0, result );
Buffer. clear ();
}
Return result;
}
Public int read (byte B [], int off, int len) throws IOException {
ByteBuffer buffer = ByteBuffer. allocate (B. length );
Int result = channel. read (buffer );
If (result! =-1 ){
Buffer. flip ();
Buffer. get (B, off, len> result? Result: len );
Buffer. clear ();
}
Return result;
}
Public void close () throws IOException {
Channel. close ();
}
}