Java NiO is used in jdk1.4, which can be said to be "new I/O", or non-blocking I/O. Here's how Java NIO works:
1. All IO events are handled by a dedicated thread and are responsible for distribution.
2. Event-driven: events are triggered when they arrive, rather than synchronized to monitor events.
3. Thread communication: The threads communicate through wait,notify and other means. Ensure that each context switch is meaningful. Reduce unnecessary thread switching.
(1) The service side of Java NiO only needs to start a dedicated thread to handle all IO events, how is this communication model implemented?
Java NIO uses two-way channels (channel) for data transfer, rather than one-way streams, which allow us to register events of interest on the channel. There are four types of events:
Event name |
corresponding values |
Server-side Receive client connection events |
Selectionkey.op_accept (16) |
Client Connection service-side events |
Selectionkey.op_connect (8) |
Read Events |
Selectionkey.op_read (1) |
Write events |
Selectionkey.op_write (4) |
(2) NiO realization principle
The server and the client each maintain a management channel object, which we call selector, which detects events on one or more channels (channel). We take the server as an example, if a read event is registered on the server's selector, at some point the client sends some data to the server, blocking I/O then calls the Read () method to block the data, and the service side of NiO adds a read event to the selector. The service-side processing thread polls the selector and, if an event of interest is found when accessing selector, handles these events and, if no event of interest arrives, the processing thread blocks until the event of interest arrives.
(3) Examples of NIO
Service side:
PackageCom.neu.nio;/*** Created by Apple on 16/7/2.*/Importjava.io.IOException;Importjava.net.InetSocketAddress;ImportJava.nio.ByteBuffer;ImportJava.nio.channels.SelectionKey;ImportJava.nio.channels.Selector;ImportJava.nio.channels.ServerSocketChannel;ImportJava.nio.channels.SocketChannel;ImportJava.util.Iterator; Public classNioserver {//Channel Manager PrivateSelector Selector; /*** Get a serversocket channel and do some initialization work on the channel * *@paramPort number bound by port *@throwsIOException*/ Public voidInitserver (intPortthrowsIOException {//get a serversocket channelServersocketchannel Serverchannel =Serversocketchannel.open (); //set channel to non-blockingServerchannel.configureblocking (false); //bind the ServerSocket of the channel to port portsServerchannel.socket (). Bind (Newinetsocketaddress (port)); //get a channel manager This. selector =Selector.open (); //binds the channel manager and the channel, and registers the Selectionkey.op_accept event for that channel, after registering the event,//when the event arrives, Selector.select () returns and blocks if the event does not reach Selector.select (). Serverchannel.register (selector, selectionkey.op_accept); } /*** Polling is used to listen for events that need to be handled on the selector, and if so, to process *@throwsIOException*/@SuppressWarnings ("Unchecked") Public voidListen ()throwsIOException {System.out.println ("The service side started successfully!" "); //Polling Access Selector while(true) { //when the registered event arrives, the method returns; otherwise, the method will always blockSelector.select (); //gets the iterator for the selected item in the selector, the selected item is the registered eventIterator ite = This. Selector.selectedkeys (). iterator (); while(Ite.hasnext ()) {Selectionkey key=(Selectionkey) ite.next (); //Remove the selected key to prevent duplicate processingIte.remove (); //Client Request Connection Event if(Key.isacceptable ()) {Serversocketchannel Server=(Serversocketchannel) key. Channel (); //get the channel to connect with the clientSocketchannel channel =server.accept (); //set as non-blockingChannel.configureblocking (false); //Here you can send a message to the client .Channel.write (Bytebuffer.wrap (NewString ("a message was sent to the client"). GetBytes ())); //after the connection with the client is successful, you need to set read permissions to the channel in order to receive the client's information. Channel.register ( This. Selector, selectionkey.op_read); //A readable event is obtained}Else if(Key.isreadable ()) {read (key); } } } } /*** Handling events that read messages sent by clients * *@paramKey *@throwsIOException*/ Public voidRead (Selectionkey key)throwsIOException {//Server readable message: Gets the socket channel where the event occurredSocketchannel channel =(Socketchannel) Key.channel (); //Create a read bufferBytebuffer buffer = bytebuffer.allocate (10); Channel.read (buffer); byte[] data =Buffer.array (); String msg=NewString (data). Trim (); System.out.println ("The server received the message:" +msg); Bytebuffer Outbuffer=Bytebuffer.wrap (Msg.getbytes ()); Channel.write (outbuffer);//to send a message back to the client } /*** Start the service-side test * *@throwsIOException*/ Public Static voidMain (string[] args)throwsIOException {nioserver server=NewNioserver (); Server.initserver (8000); Server.listen (); }}
Client:
PackageCom.neu.nio;/*** Created by Apple on 16/7/2.*/Importjava.io.IOException;Importjava.net.InetSocketAddress;ImportJava.nio.ByteBuffer;ImportJava.nio.channels.SelectionKey;ImportJava.nio.channels.Selector;ImportJava.nio.channels.SocketChannel;ImportJava.util.Iterator; Public classnioclient {//Channel Manager PrivateSelector Selector; /*** Start Client Test * *@throwsIOException*/ Public Static voidMain (string[] args)throwsIOException {nioclient client=Newnioclient (); Client.initclient ("LocalHost", 8000); Client.listen (); } /*** Get a socket channel and do some initialization work on the channel * *@paramIP of the IP-connected server *@paramPort number of the server to which the port is connected *@throwsIOException*/ Public voidInitclient (String IP,intPortthrowsIOException {//get a socket channelSocketchannel channel =Socketchannel.open (); //set channel to non-blockingChannel.configureblocking (false); //get a channel manager This. selector =Selector.open (); //The client connects to the server, in fact the method execution does not implement the connection, need in the Listen () method to tune//use Channel.finishconnect () to complete the connectionChannel.connect (Newinetsocketaddress (IP, port)); //binds the channel manager and the channel, and registers the Selectionkey.op_connect event for that channel. Channel.register (selector, selectionkey.op_connect); } /*** Polling is used to listen for events that need to be handled on the selector, and if so, to process *@throwsIOException*/@SuppressWarnings ("Unchecked") Public voidListen ()throwsIOException {//Polling Access Selector while(true) {selector.select (); //gets the iterator for the selected item in the selectorIterator ite = This. Selector.selectedkeys (). iterator (); while(Ite.hasnext ()) {Selectionkey key=(Selectionkey) ite.next (); //Remove the selected key to prevent duplicate processingIte.remove (); //Connection event occurs if(Key.isconnectable ()) {Socketchannel channel=(Socketchannel) key. Channel (); //If you are connecting, complete the connection if(Channel.isconnectionpending ()) {channel.finishconnect (); } //set as non-blockingChannel.configureblocking (false); //here, you can send messages to the server.Channel.write (Bytebuffer.wrap (NewString ("Send a message to the server")). GetBytes ())); //after the connection with the server is successful, in order to receive the information from the server, you need to set the Read permission to the channel. Channel.register ( This. Selector, selectionkey.op_read); //A readable event is obtained}Else if(Key.isreadable ()) {read (key); } } } } /*** Handling events that read information sent from the service side * *@paramKey *@throwsIOException*/ Public voidRead (Selectionkey key)throwsIOException {//same as the Read method on the service side//Client-readable message: Gets the socket channel where the event occurredSocketchannel channel =(Socketchannel) Key.channel (); //Create a read bufferBytebuffer buffer = bytebuffer.allocate (10); Channel.read (buffer); byte[] data =Buffer.array (); String msg=NewString (data). Trim (); System.out.println ("Client received message:" +msg); Bytebuffer Outbuffer=Bytebuffer.wrap (Msg.getbytes ()); Channel.write (outbuffer);//send a message back to the server }}
Reference: http://weixiaolu.iteye.com/blog/1479656
Principles and examples of Java NiO