NIO's use
The new I / O class library is released in J2SE 1.4 or later. This article will briefly introduce some of the new features provided by the NIO library by some examples: non-blocking I / O, characters conversion, buffering, and channels.
I. Introduction of the nionio package (java.nio. *) Introduced four critical abstract data types, which solved some of the problems in the traditional I / O class. 1. Buffer: It is a line table structure that contains data and is used to read and write. It also provides an I / O operation for a special class for memory mapping files. 2. Charset: It provides a Unicode string to be imaged to the byte sequence and the operation of the reverse image. 3. Channels: The three pipes containing socket, file, and pipes are actually a channel between bidirectional communication. 4. Selector: It focuses multiple asynchronous I / O operations into one or more threads (it can be seen as an object-oriented version of the waitforsingleEvent () function in UNIX in a select () function or Win32). 2. Review the tradition before introducing NIO, it is necessary to understand the traditional I / O operation. Taking network applications as an example, traditional ways need to listen to a serverSocket, accepting the connection to provide services (service usually includes processing requests and transmit responses) Figure 1 is the life cycle diagram of the server, where there is a part of the crude black line indicates I / O blocking occurs. Figure 1 can analyze each of the specific steps of the server. First create a ServerSocket ServerSocket Server = New ServerSocket (10000); then accept new connection requests socket newconnection = server.accept (); the call to the Accept method will cause block until Serversocket accepts a connection request. Once the connection request is accepted, the server can read the request in the customer socket. InputStream in = newConnection.getInputStream (); InputStreamReader reader = new InputStreamReader (in); BufferedReader buffer = new BufferedReader (reader); Request request = new Request (); (! Request.isComplete ()) while {String line = buffer. Readline (); Request.addline (LINE);} There are two problems, first of all, the bufferedreader class () method of the BufferedReader class causes the thread blocking in its buffer, and only a certain amount of data is filled with buffer or customers. Close the socket, the method will return. Second, it returns a large amount of garbage, and BufferedReader creates a buffer to read data from the client socket, but some strings are created to store this data. Although StringBuffer handles this issue inside the bufferedReader, all String has quickly become a waste of garbage.
The same problem exists in transmitting the response code Response response = request.generateResponse (); OutputStream out = newConnection.getOutputStream (); InputStream in = response.getInputStream (); int ch;! While (-1 = (ch = in .read ())) {out.write (ch); newconnection.close (); Similar, read and write operation is blocked and written to a character in the stream will cause low efficiency, so the buffer should be used, but Once the buffer is used, the flow will produce more garbage. Traditional solutions typically process blocking I / O to use threads (a large number of threads) in Java. Generally, a thread pool is implemented to handle requests, as shown in Figure 2, the server can handle multiple connections, but they also trigger a lot. Each thread has its own stack space and occupies some CPU times, which is costly, and many times is wasted in blocking I / O operations, and there is no effective use of CPUs. III. New I / O1. Buffer Traditional I / O Continuous Waste Object Resources (usually String). New I / O avoids resource waste by using the buffer read and write data. Buffer objects are linear, orderly data sets, which contain only unique data types according to their category. Java.nio.buffer class description java.nio.bytebuffer includes byte type. You can read Java.Nio.mappedBytebuffer from ReadableBytechannel in the WritableBytechannel, which contains the byte type, and maps java.nio.charbuffer directly in the memory. java.nio.FloatBuffer float into the channel comprises comprising an int type java.nio.IntBuffer java.nio.LongBuffer type comprising long java.nio.ShortBuffer comprising short type by calling allocate (int capacity) method or allocateDirect (int capacity) method Assign a buffer. Special, you can create mappedbytesbuffer by calling FileChannel.Map (int MAP (int MODE). Direct Buffer assigns a continuous block in memory and read and write data using the local access method. Non Direct (Nondirect) Buffer reads and write data by using an array in Java. Sometimes you have to use non-direct buffering, for example, any WRAP method (such as bytebuffer.wrap (byte [])) creates a buffer based on the Java array. 2. The character encoding is stored in Bytebuffer involves two problems: the order and character conversion of bytes. Bytebuffer handles byte order issues through the ByteORDER class, but does not process the character conversion. In fact, Bytebuffer has no way to read and write string. Java.nio.charset.Charset handles characters conversion issues. It converts the character sequence into bytes and reverse transitions by constructing CharsetEncoder and CharsetDecoder. 3. Channel You may notice that there is no read and write buffer type in the existing Java.IO class, so the Channel class is provided in NIO to read the Buffer.
The channel can be considered to be a connection, which can be a connection to a particular device, a program or a network. The class level of the channel is shown in Figure 3 in the three drawing of ReadableBytechannel and WritableBytechannel for reading and writing, respectively. GatheringBytechannel can write from multiple buffers in multiple buffers using a multiple buffer to read data from channels in multiple buffers at a time. You can also set the channel to make it blocked or non-blocking I / O operation services. In order to make the channels can be compatible with traditional I / O classes, the CHANNEL class provides a static method to create stream or reader4. Selector In the past block I / O, we generally know when you can read or write to the Stream, because the method calls returns until stream is ready. But use non-blocking channels, we need some ways to know when the channel is ready. In the NIO package, the design Selector is for this purpose. SelectableChannel can register a specific event instead of notifying the application when an event occurs, channel tracking events. Then, when the application calls any of the Selection method on the Selector, it is viewed to see if there is any incident of interest in the registered channel. Figure 4 is an example of Selector and two registered channels that are not all channels support all operations. The SelectionKey class defines all possible operational bits, which will be used twice. First, when the application calls the SelectableChannel.Register (Selector SEL, INT OP) method registration channel, it passes the required operation as the second parameter to the method. Then, once the SelectionKey is selected, SelectionKey's readyOps () method returns the number of all channel support operations. SelectableChannel's Validops method returns the operations allowed for each channel. The registration channel does not support will trigger an unlegalargumentException exception. The following table lists the operations supported by SelectableChannel subclasses. ServersocketChannel OP_ACCEPT SOCKETCHANNEL OP_CONNECT, OP_READ, OP_WRITE DATAGRAMCHANNEL OP_READ, OP_WRITE PIPE.SOURCHANNEL OP_READ PIPE.SINKCHANNEL OP_WRITE
4. Example 1. Simple web content download This example is very simple, class SocketChannelReader uses SocketChannel to download the HTML content of a specific web page. Package examples.nio;
Import java.nio.bytebuffer; import java.nio.channel; import java.nio.charset.charset; import java.net.inetsocketaddress; import java.io ioException;
Public class socketchannelreader {private charset charset = charset.Forname ("UTF-8"); // Create a UTF-8 character set Private socketchannel channel;
Public void gethtmlcontent () {Try {connection (); sendRequest (); readResponse ();} catch (ooException e) {system.err.println (e.tostring ());} finally {ix (channel! = null) {try {channel.close ();} catch (IOException e) {}}}} private void connect () throws IOException {// connected to 9CBS InetSocketAddress socketAddress = new InetSocketAddress ( "www.9cbs.net", 80); Channel = SocketChannel.open (socketaddress); // Use the factory method Open to create a CHANNEL and connect it to the specified address // quite with socketchannel.open (). Connect (socketaddress); call} private void sendrequest () THROWS IOEXCEPTION {CHANNEL.WRITE (Charset.Encode ("get" "/ Document")); // Send a GET request to 9CBS document center // Use the Channel.Write method, it The parameters of the CHARBYTE type are required to convert the string using the //charset.encode(String) method. }
Private void readResponse () throws ioException {// read answers Bytebuffuffer buffer = bytebuffer.allocate (1024); // Create 1024 bytes of buffer while (Channel.Read (buffer)! = - 1) {buffer.flip () The // FLIP method is called before the buffer byte operation. System.out.println (charset.decode (buffer); // convert byte to string buff.clear (); // Clear buffer}
Public static void main (string [] args) {new socketchannel (). gethtmlcontent ();} 2. Simple addition server and client server code package examples.nio;
import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.net.InetSocketAddress; import java.io.IOException;
/ ** * SUMSERVER.JAVA * * * CREATED: THU NOV 06 11:41:52 2003 * * @Author starchu1981 * @version 1.0 * / public class sumserver {
private ByteBuffer _buffer = ByteBuffer.allocate (8); private IntBuffer _intBuffer = _buffer.asIntBuffer (); private SocketChannel _clientChannel = null; private ServerSocketChannel _serverChannel = null; public void start () {try {openChannel (); waitForConnection ();} Catch (ioException e) {system.err.println (e.tostring ());}}
Private void openchannel () throws oException {_serverchannel = serversocketchannel.open (); _ServerChannel.socket (). Bind (New InetSocketAddress); system.out.println ("Server channel has been opened);}
private void waitForConnection () throws IOException {while (true) {_clientChannel = _serverChannel.accept (); if (_clientChannel = null!) {System.out.println ( "Add new connection"); processRequest (); _ clientChannel.close ()}}}
Private void processRequest () throws oException {_buffer.clear (); _clientChannel (); int result = _intbuffer.get (0) _ intbuffer.get (1); _Buffer.flip (); _buffer.clear (); _intbuffer.put (0, result); _clientChannel.write (_buffer);
Public static void main (string [] args) {new sumserver (). start ();}} // Sumserver customer code package examples.nio;
Import java.nio.bytebuffer; import java.nio.intbuffer; import java.nio.channel; import java.net.InetSocketAddress; import java.io ioException;
/ ** * Sumclient.java * * * created: THU NOV 06 11:26:06 2003 * * @Author starchu1981 * @version 1.0 * / public class sumclient {
Private botebuffer _buffer = bytebuffer.allocate (8); private intbuffer _intbuffer; private socketchannel _channel;
public SumClient () {_intBuffer = _buffer.asIntBuffer ();} // SumClient constructor public int getSum (int first, int second) {int result = 0; try {_channel = connect (); sendSumRequest (first, second); result = ReceiveResponse ();} catch (ioException e) {system.err.println (e.tostring ());} finally {if (_channel! = null) {Try {_Channel.close ();} catch (ooException e) {}}} return result;} private SocketChannel connect () throws IOException {InetSocketAddress socketAddress = new InetSocketAddress ( "localhost", 10000); return SocketChannel.open (socketAddress);} private void sendSumRequest (int first, int second) throws IOException {_Buffer.clear (); _intBuffer.put (0, first); _intBuffer.put (1, second); _Channel.Write (_buffer); system.out.println ("send addition request" first " " SECOND ); Private int received {_buffer.clear (); _Channel.Read (_buffer); return_intbuffer.get (0);}
Public static void main (string [] args) {Sumclient Sumclient = new sumclient (); System.out.Println ("The addition result is:" Sumclient.getsum (100, 324));}} // sumclient3. Non-blocking addition servers first add statements to the OpenChannel method_ServerChannel.configureBlocking (FALSE); // Set to become non-blocking mode
The code to rewrite the WaitForConnection method is as follows, using Non-Blocking Method Private Void WaitForConnection () thRows IOException {Selector AcceptSelector = selectorProvider.Provider (). OpenSelector ();
/ * Register the selector on the server socket and set to accept the notification of the Accept method. This tells Selector, the socket wants to be placed on the Ready table when the Accept operation occurs, so the multi-element non-blocking I / O occurs. * / SelectionKey AcceptKey = SSC.Register (AcceptSelector, SelectionKey.op_Accept); int keydded = 0; / * SELECT method returns * / while ((Keysadded = AcceptSelector.select ()) in any of the above registered operations ) {// A customer is ready to perform I / O operation, get its ready key collection set readyKeys = acceptSelector.selectedKeys (); item i = readyKeys.ITERATOR (); // Traverse the Ready button collection, and process the addition Request While (I.HASNext ()) {SelectionKey Sk = (SelectionKey) i.next (); i.remove (); ServersocketChannel NextReady = (ServersocketChannel) sk.channel (); // Accept the addition request and process it _ClientSocket = NextReady.accept (). socket (); processRequest (); _clientsocket.close ();}}}
Reference 1.
Disclaimer: Please transfer the transfer, please