1. BIO
Before JDK5, the JDK io mode was only bio (synchronous blocking)
Problem: Because of the presence of blocking, you need to open a thread for each request. Excessive thread switching affects operating system performance
WORKAROUND: Use the thread pool to handle the queue that cannot be processed, and then the other mechanism will be triggered.
Problem: Requests that exceed the number of thread pools need to wait
public class Client { final static String ADDRESS = "127.0.0.1"; Final static int PORT = 8765; public static void Main (string[] args) throws IOException { socket socket = NULL; BufferedReader in = null; PrintWriter out = null; try { socket = new Socket (ADDRESS, PORT); in = new BufferedReader (New InputStreamReader (Socket.getinputstream ())); out = new PrintWriter (Socket.getoutputstream (), true); True automatically flush //Send data out.println ("Request from client") to server side; Data received from the server String response = In.readline (); Block System.out.println ("Client Fetch data:" + response); } catch (Exception e) { e.printstacktrace (); } finally { out.close (); In.close (); Socket.close ();}}}
Server 1: One request ~ one thread
public class Server {final static int PROT = 8765; public static void Main (string[] args) throws IOException {ServerSocket server = null; try {server = new ServerSocket (PROT); SYSTEM.OUT.PRINTLN ("server Start"); while (true) {Socket socket = server.accept (); The listener is blocked, and the socket base creates a new thread to handle the three-time handshake with the client//to establish the socket new thread (socket) acquired by the threading process. Start (); }} catch (Exception e) {e.printstacktrace (); } finally {server.close (); }}}class Serverhandler implements Runnable {private socket socket; Public Serverhandler (socket socket) {this.socket = socket; } @Override public void Run () {bufferedreader in = null; PrintWriter out = null; try {in = new BufferedReader (New InputStreamReader (This.socket.getInputStream ())); out = new PrintWriter (this.socket.getOutputStreAM (), true); String BODY = null; while (true) {BODY = In.readline (); Block if (BODY = = null) break; SYSTEM.OUT.PRINTLN ("Server gets request:" + body); OUT.PRINTLN ("Response from server"); }} catch (Exception e) {e.printstacktrace (); } finally {try {out.close (); In.close (); Socket.close (); } catch (IOException e) {e.printstacktrace (); } } }}
Server 2: Processing requests with the thread pool
public class Server {final static int PORT = 8765; public static void Main (string[] args) throws IOException {ServerSocket server = null; try {server = new ServerSocket (PORT); SYSTEM.OUT.PRINTLN ("server Start"); Handlerexecutorpool Executorpool = new Handlerexecutorpool (50, 1000); while (true) {Socket socket = server.accept (); Executorpool.execute (new Serverhandler (socket)); }} catch (Exception e) {e.printstacktrace (); } finally {server.close (); }}}class handlerexecutorpool {private Executorservice executor; Public Handlerexecutorpool (int maxpoolsize, int queuesize) {this.executor = new Threadpoolexecutor (//thread pool with blocking queue Runtime.getruntime (). Availableprocessors (),//initial thread Count maxpoolsize,//maximum number of threads if you want to process the requested R Unnable objects are filled with queues, increase the number of existing threads by 120L,//As in 120 time particles a thread isIdle, will be recycled timeunit.seconds, new arrayblockingqueue<runnable> (queuesize)//Store processing request for run Nable object); public void execute (Runnable task) {This.executor.execute (Task); }}class Serverhandler implements Runnable {private socket socket; Public Serverhandler (socket socket) {this.socket = socket; } @Override public void Run () {bufferedreader in = null; PrintWriter out = null; try {in = new BufferedReader (New InputStreamReader (This.socket.getInputStream ())); out = new PrintWriter (This.socket.getOutputStream (), true); String BODY = null; while (true) {BODY = In.readline (); if (BODY = = null) break; SYSTEM.OUT.PRINTLN ("Server gets request:" + body); Block Out.println ("Response from server"); }} catch (Exception e) {e.printstacktrace (); } finally { try {out.close (); In.close (); Socket.close (); } catch (IOException e) {e.printstacktrace (); } } }}
2.nio1.0
JDK5 introduced the NIO1.0 (multiplexing mechanism)
Adjoint multiplexing introduces the following concepts into the program:
Channel (channel): The abstraction of a TCP connection, a TCP connection that corresponds to multiple channels, which reduces the number of connections to TCP.
Channel similar to the socket in bio
Channels are similar to streams in bio, but the channel is bidirectional and the flow is unidirectional
Channel has multiple status bits that can be identified by selector
Buffer (buffer):
A buffer is an area of memory (an array) that is wrapped in NiO as a buffer object. Buffer provides methods to access the memory.
In bio, data is stored in a stream, and in NiO, the data is stored in a buffer.
In addition to the Boolean other Java seven basic types have the corresponding buffer class. Most commonly used is the Bytebuffer
Selector (multiplexer): Responsible for polling all registered channels and performing related operations based on channel status. The status includes: Connect,accept,read,write.
In the "four commonly used IO models", the use of select system calls for IO multiplexing is mentioned. Linux also provides a poll/epoll function in addition to select, where the Select/poll function scans the file handle in order to be ready and supports a limited number of file handles; Instead, Epoll uses an event-driven alternative to sequential scanning, with higher performance and no limit on the number of file handles. The JDK's selector uses epoll, which requires only one thread to poll and can access a large number of clients.
public class Client {public static void main (string[] args) throws IOException {Socketchannel sc = null; Bytebuffer writebuf = bytebuffer.allocate (1024); Bytebuffer readbuf = bytebuffer.allocate (1024); try {//create Channel SC = Socketchannel.open (); Connection Sc.connect (New inetsocketaddress ("127.0.0.1", 8765)); The following steps can be used selector polling instead of while (true) {///define a byte array and then use the System entry function: byte[] bytes1 = new by TE[1024]; System.in.read (BYTES1); Block//Put data into buffer writebuf.put (BYTES1); The buffer is reset Writebuf.flip (); Write Data Sc.write (WRITEBUF); Emptying buffer writebuf.clear (); Receive service-side response Sc.read (READBUF); Readbuf.flip (); byte[] Bytes2 = new byte[readbuf.remaining ()]; Readbuf.get (byTES2); Readbuf.clear (); String BODY = new string (bytes2); SYSTEM.OUT.PRINTLN ("Client gets data:" + body); }} catch (IOException e) {e.printstacktrace (); } finally {sc.close (); } }}
Control and client read/write sequencing by changing the status bit of the selector monitor channel
public class Server implements runnable{private Selector seletor; Private Bytebuffer Readbuf = bytebuffer.allocate (1024); Private Bytebuffer Writebuf = bytebuffer.allocate (1024); public Server (int port) {try {//1 creates a multiplexer Selector This.seletor = Selector.open (); 2 Create ServerSocket channel Serversocketchannel SSC = Serversocketchannel.open (); 3 sets whether the channel is blocked, determines whether the channel Read/write/accept/connect method is blocking ssc.configureblocking (false); 4 Set the channel address Ssc.bind (new inetsocketaddress (port)); 5 Register the ServerSocket channel on the selector, and specify to listen for its ACCEPT event Ssc.register (This.seletor, selectionkey.op_accept); System.out.println ("Server start"); } catch (IOException e) {e.printstacktrace (); }} @Override public void Run () {while (true) {try {//select block, listen for related events This.seletor.select (); Unblocking,Return select key, key contains channel, status and other information iterator<selectionkey> Keysiter = This.seletor.selectedKeys (). Iterator (); Traversing while (Keysiter.hasnext ()) {Selectionkey key = Keysiter.next (); Keysiter.remove (); if (Key.isvalid ()) {//wait for Receive connection status if (Key.isacceptable ()) { Accept (key); }//Readable state if (key.isreadable ()) {read (key); } if (Key.iswritable ()) {write (key); }}}} catch (IOException e) {e.printstacktrace (); }}} private void Write (Selectionkey key) {try {//Get channel Socke TChannel sc = (socketchannel) key.channel (); Write back to the client data writebuf.put ("Response from server". GetBytes ()); Writebuf.flip (); Sc.write (WRITEBUF); Writebuf.clear (); Modify the state bit of the listener, if the hold op_write will cause duplicate write key.interestops (selectionkey.op_read); } catch (IOException e) {e.printstacktrace (); }} private void Read (Selectionkey key) {try {//get channel Socketchannel sc = (Socketchann EL) Key.channel (); Read the data and read the buffer. According to the program run order, here the SC is set to the blocking effect is the same as int count = Sc.read (THIS.READBUF); READBUF will change the value of position if (count = =-1) {Key.channel (). Close (); Key.cancel (); Cancels the registration of the channel in selector, and will not be consulted by the select polling return; }//There is data to read. Position and limit must be reset before reading Readbuf.flip (); Creates a byte array of the corresponding size based on the data length of the buffer, receiving buffer data byte[] bytes = new byte[this.readbuf.remaining ()]; Receive buffer Data readbuf.get (bytes); Readbuf.clear (); String BODY = new String (bytes). Trim (); SYSTEM.OUT.PRINTLN ("Server gets request:" + body); If keeping op_read will result in repeated reading of Sc.register (This.seletor, selectionkey.op_write); } catch (IOException e) {e.printstacktrace (); }} private void Accept (Selectionkey key) {try {//Get service channel Serversocketchannel SSC = (Serversocketchannel) Key.channel (); Gets the client channel. Socketchannel sc = ssc.accept (); Set non-blocking mode sc.configureblocking (false); Registering the client channel on the multiplexer, specifying the Listener event Sc.register (This.seletor, Selectionkey.op_read | Selectionkey.op_write); } catch (IOException e) {e.printstacktrace (); }} public static void Main (string[] args) {new Thread (new Server (8765)). Start (); }}
The Bio client communicates with the NIO server to be aware of:
Bio server, once IO has a definite end point, the client again read will return-1
After the NIO service end of an IO, no channel is closed, it may turn the channel from read state to write state. So selector do not listen to read, the client again read nothing back, it will block.
3.nio2.0
JDK7 introduced NIO2.0 (i.e. AIO)
In NIO1.0, the IO process is not blocked and the blocking is shifted to the selector poll. Selector manages all channel, so it can gross position blocking time to a minimum.
In NIO2.0, the IO API for us to invoke is non-blocking, and the complex implementation process behind it (there must be blocking) is transferred to the bottom of the JDK and the operating system. The IO Call of our program can be returned immediately.
There are also channel and buffer, but no selector
public class Server {//thread pool private executorservice executorservice; Asynchronous channel thread Group private Asynchronouschannelgroup Threadgroup; Server channel public Asynchronousserversocketchannel ASSC; public Server (int port) {try {//Create a thread pool Executorservice = Executors.newcachedthreadpool (); Use the thread pool to create an asynchronous channel thread group that supports our asynchronous operations Threadgroup = Asynchronouschannelgroup.withcachedthreadpool (Execu Torservice, 1); Create a server channel using an asynchronous channel thread Group ASSC = Asynchronousserversocketchannel.open (Threadgroup); Bind Port Assc.bind to channel (new Inetsocketaddress (port)); SYSTEM.OUT.PRINTLN ("server Start"); The following accept will not block, an accept can only receive a connection request//Accept the first parameter: The associated object (subclass) that is bound to the IO operation, the second parameter Completionhandler<asynchronou Ssocketchannel, associated object (parent class); The callback handle executed after the operation succeeds//If a new connection is accepted, the result Asynchronoussocketchannel will be bound to the ASSC channel to the same asynchron Ouschannelgroup assc.accept (this, new servercompleTionhandler ()); In order to avoid the end of the program, the asynchronous channel thread group end will not execute callback Thread.Sleep (Integer.max_value); } catch (Exception e) {e.printstacktrace (); }} public static void Main (string[] args) {new Server (8765); } }
First parameter: IO operation result; Second parameter: The associated object that is bound to the IO operation public class Servercompletionhandler implements Completionhandler<asynchronoussocketchannel, server> {///The following two overloaded parameters are consistent with the template parameters of the Completionhander, the associated object that is set when the callback is passed into the IO result and IO operation @Override public void completed (ASYNCHR Onoussocketchannel ASC, Server Attachment) {//When the current connection is completed, first, the next client can access the Accept Async method again attachment.assc.accept (attachment, this); Second, perform the next reading of Read (ASC); } @Override public void failed (Throwable exc, Server attachment) {exc.printstacktrace (); } private void Read (final asynchronoussocketchannel ASC) {//Read data Bytebuffer buf = bytebuffer.allocate (10 24); First parameter: Buffer for read operation, second parameter: Io association object, third parameter: Completionhandler<integer, IO Management Object parent > Asc.read (buf, buf, new comple Tionhandler<integer, bytebuffer> () {@Override public void completed (Integer resultsize, Byteb Uffer attachment) {//After reading, reset the identity bit attachmenT.flip (); Gets the number of bytes read System.out.println ("Server Side" + "received the client's data length as:" + resultsize); Gets the data read by string resultdata = new String (Attachment.array ()). Trim (); SYSTEM.OUT.PRINTLN ("Server Side" + "received the client's data information as:" + resultdata); String response = "From server to client: on" + New Date () + "request data received" + Resultdata; Write (ASC, response); } @Override public void failed (Throwable exc, bytebuffer attachment) {Exc.printstack Trace (); } }); private void Write (Asynchronoussocketchannel ASC, String response) {try {bytebuffer buf = Byt Ebuffer.allocate (1024); Buf.put (Response.getbytes ()); Buf.flip (); Write operation, asynchronous future<integer> future = Asc.write (BUF); Blocking wait results future.get (); } catch (Interruptedexception e) {e.printstacktrace (); } catch (Executionexception e) {e.printstacktrace (); } }}
public class Client {private asynchronoussocketchannel ASC; Public Client () throws Exception {ASC = Asynchronoussocketchannel.open (); } public void Connect () throws Interruptedexception, executionexception{//Get () block Asc.connect (new I Netsocketaddress ("127.0.0.1", 8765)). get (); } public void write (String request) {try {//Get () Block Asc.write (Bytebuffer.wrap (reques T.getbytes ())). get (); Read (); } catch (Exception e) {e.printstacktrace (); }} private void Read () throws IOException {Bytebuffer buf = bytebuffer.allocate (1024); try {//Get () block Asc.read (BUF). get (); Buf.flip (); byte[] Respbyte = new byte[buf.remaining ()]; Buf.get (Respbyte); System.out.println (New String (Respbyte, "utf-8"). Trim ()); Close Asc.close (); } catch (Interruptedexception e) {E.priNtstacktrace (); } catch (Executionexception e) {e.printstacktrace (); } catch (Unsupportedencodingexception e) {e.printstacktrace (); }} public static void Main (string[] args) throws Exception {Client C1 = new Client (); Client C2 = new Client (); C1.connect (); C2.connect (); C1.write ("AA"); C2.write ("BBB"); }}
Java IO------------------BIO (synchronous blocking), NIO1.0 (multiplexed), NIO2.0 (AIO, non-blocking)