About blocking and non-blocking: https://www.cnblogs.com/jhxxb/p/11272727.html
First, the traditional IO streams are blocking the
When a thread calls read () or write (), the thread is blocked until there is some data to be read or written to, the thread in the meantime can not perform other tasks.
Therefore, when the communication network IO operation, because the thread is blocked, so the server must have a separate thread for processing for each client, when the server needs to handle large number of clients, a sharp decline in performance.
package nio; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Scanner; public class TestBlockingNIO { // 客户端 @Test public void client() throws IOException { // 获取通道 SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); // allocate a buffer size specified the ByteBuffer buf = ByteBuffer.allocate (1024 ); // sent to the server Scanner Scan = new new Scanner (the System.in); the while (scan.hasNext ()) { String STR = scan.next (); buf.put (str.getBytes ()); buf.flip (); sChannel.write (buf); buf.clear (); IF ( "Exit" .equals (STR)) { BREAK ; } } // receiving feedback service side sChannel.shutdownOutput (); int len = 0; The while (! (Len = sChannel.read (buf)) = -1 ) { buf.flip (); System.out.println ( new new String (buf.array (), 0 , len)); buf.clear ( ); } // close the passage sChannel.close (); } // server @Test public void Server () throws IOException { // acquisition channel a ServerSocketChannel ssChannel = ServerSocketChannel.open (); // bound connection ssChannel.bind ( new new the InetSocketAddress (9898 )); the retry: the while ( to true ) { // acquisition channel client connection the SocketChannel Schannel = ssChannel.accept (); // allocate a buffer size specified the ByteBuffer buf = ByteBuffer.allocate (1024 ); // receiving the client's data the while ( ! sChannel.read (buf) = -1 ) { String STR = new new String (buf.array ()) TRIM. (); IF ( "Exit" .equals (STR)) { BREAK the retry; } buf.flip () ; System.out.println (STR); buf.clear (); } // send back to the client buf.put ( "the server successfully receives the data!" .getBytes ()); buf.flip (); sChannel.write (buf); // Close Channel sChannel .close (); } // close the passage ssChannel.close (); } }
Two, Java NIO is non-blocking
When the thread to read and write data from a channel, if no data is available, the thread can perform other tasks.
The threads are usually non-blocking IO idle time for performing IO operations on other channels, so a separate thread to manage a plurality of input and output channels.
Therefore, NIO allows the server to use one or a limited number of threads to simultaneously handle all client connections to the server.
Note: IO NIO or synchronous behavior.
/ * * NIO completed using three core communication network: * * 1. channels (Channel): responsible for connecting * java.nio.channels.Channel Interface: * | --SelectableChannel * | --SocketChannel * | --ServerSocketChannel * | --DatagramChannel * * | --Pipe.SinkChannel * | --Pipe.SourceChannel * * 2. buffer (buffer): responsible for data access * * 3. selector (selector): is a multiplexed SelectableChannel Appliances. IO is used to monitor the status of SelectableChannel * can listen to the type of event (using four constants SelectionKey representation) * Reading: SelectionKey.OP_READ (1) * wrote: SelectionKey.OP_WRITE (4) * connection: SelectionKey.OP_CONNECT (8) * reception: SelectionKey.OP_ACCEPT (16) * * Selector conventional method * Set <SelectionKey> keys () : set all SelectionKey. Registered on behalf of the Selector Channel * selectedKeys (): selected SelectionKey collection. Returns the selected key set Selector * intselect (): monitoring all registered Channel, when the intermediate IO operations they have to be processed, the method returns, and the corresponding SelectionKey was added SelectionKey set is selected, the method returns the number of these Channel. * Int select (long timeout): You can set a long timeout select () operation * int selectNow (): Returns the immediate implementation of a select () operation, which does not block the thread * Selector wakeup (): make a return yet the select () method returns immediately * void close (): close the selector * /
1.TCP-SocketChannel
package nio; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Date; import java.util.Iterator; import java.util.Scanner; public class TestNonBlockingNIO { //客户端 @Test public void client() throws IOException { // acquisition channel the SocketChannel the SocketChannel.open Schannel = ( new new the InetSocketAddress ( "127.0.0.1", 9898 )); // switch nonblocking sChannel.configureBlocking ( to false ); // allocate the specified buffer size ByteBuffer buf ByteBuffer.allocate = (1024 ); // send data to the server Scanner Scan = new new Scanner (the System.in); the while (scan.hasNext ()) { String STR = scan.next (); buf.put (( new new . DATE () toString () + "\ n-" + STR) .getBytes ()); buf.flip (); sChannel.write (buf); buf.clear (); } // close the passage sChannel.close (); } // server @Test public void Server () throws IOException { // acquisition channel ServerSocketChannel = ssChannel ServerSocketChannel.open (); // switch nonblocking ssChannel.configureBlocking ( to false ); // bind connection ssChannel.bind ( new new the InetSocketAddress (9898 )); // Get selector selector selector = Selector.open (); // will be registered on the channel selector, and specify "monitor received event" ssChannel.register (Selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_READ); // the polled have acquired selector "ready" event while (selector.select ()> 0 ) { // get all registered "selection key (ready listener events)" current selector Iterator <SelectionKey> IT = selector.selectedKeys () Iterator ();. the while (IT .hasNext ()) { // get ready to "ready" is an event SelectionKey SK = it.next (); // determine what specific event ready IF (sk.isAcceptable ()) { // if "ready to receive" obtain client connection Schannel = the SocketChannel ssChannel.accept (); // switch nonblocking sChannel.configureBlocking ( to false ); // the channel registered on the selector sChannel.register (Selector, SelectionKey.OP_READ); } the else IF (sk.isReadable ()) { // get the current selector on the "read ready" state of the channel the SocketChannel Schannel = (the SocketChannel) sk.channel (); // read the data the ByteBuffer buf = ByteBuffer.allocate (1024 ); int len = 0 ; while (( sChannel.read = len (buf))> 0 ) { buf.flip(); System.out.println(new String(buf.array(), 0, len)); buf.clear(); } } // 移除当前 SelectionKey it.remove(); } } } }
2.UDP-DatagramChannel
package nio; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Date; import java.util.Iterator; import java.util.Scanner; public class TestNonBlockingNIO2 { @Test public void send() throws IOException{ DatagramChannel dc = DatagramChannel.open(); dc.configureBlocking(false); ByteBuffer buf = ByteBuffer.allocate(1024); Scanner scan = new Scanner(System.in); while(scan.hasNext()){ String str = scan.next(); buf.put((new Date().toString() + ":\n" + str).getBytes()); buf.flip(); dc.send(buf, new InetSocketAddress("127.0.0.1", 9898)); buf.clear(); } dc.close(); } @Test public void receive() throws IOException{ DatagramChannel dc = DatagramChannel.open(); dc.configureBlocking(false); dc.bind(new InetSocketAddress(9898)); Selector selector = Selector.open(); dc.register(selector, SelectionKey.OP_READ); while(selector.select() > 0){ Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while(it.hasNext()){ SelectionKey sk = it.next(); if(sk.isReadable()){ ByteBuffer buf = ByteBuffer.allocate(1024); dc.receive(buf); buf.flip(); System.out.println(new String(buf.array(), 0, buf.limit())); buf.clear(); } } it.remove(); } } }
Three, Pipe (pipe)
Java NIO pipes are unidirectional data connection between the two threads. Pipe passage has a source and a sink channel. Sink channel data will be written, it is read from the source channels.
Package NiO; Import org.junit.Test; Import java.io.IOException; Import java.nio.ByteBuffer,; Import java.nio.channels.Pipe; public class TestPipe { @Test public void Test () throws IOException { // Get pipe pipe pipe = Pipe.open (); the ByteBuffer buf = ByteBuffer.allocate (1024 ); buf.put ( "one-way data transmission pipe" .getBytes ()); buf.flip (); // the buffer data write pipe Pipe.SinkChannel sinkChannel = pipe.sink(); sinkChannel.write(buf); ByteBuffer buf2 = ByteBuffer.allocate(1024); // 读取缓冲区中的数据 Pipe.SourceChannel sourceChannel = pipe.source(); int len = sourceChannel.read(buf2); System.out.println(new String(buf2.array(), 0, len)); sourceChannel.close(); sinkChannel.close(); } }