Before JDK 1.4, Java's IO operation is concentrated in Java.IO, which is a Blocking API. For most applications, such API is very convenient, however, some applications with higher performance requirements, especially server applications, often require a more effective way to process IO. From JDK 1.4, the NIO API is an API that is buffer based on a buffer and provides a non-blocking IO operation. This article introduces it in depth.
The NIO API is mainly focused on java.nio and its Subpackages:
Java.nio defines the subclass related to the Buffer and its data types. The role of Bytebuffer used in java.nio.channels used to perform IO operations.
Java.nio.channels defines a series of Channel interfaces that handle IO and these interfaces on file systems and network communication. With the class of Selector, it also provides a way to perform non-blocking IO operations. This package can be said to be the core of the NIO API.
Java.nio.channels.SPI defines an abstract class that can be used to implement the Channel and Selector API.
Java.nio.Charset defines classes that process character encoding and decoding.
Java.nio.charset.SPI defines an abstract class that can be used to implement the Charset API.
Java.Nio.Channels.SPI and java.nio.charset.spi These two packages are mainly used to extend existing Nio APIs. In actual use, we generally only deal with additional 3 packages. Here will be introduced one by one below.
Package java.nio
This package mainly defines the buffer and its subclasses. Buffer defines a container interface that linearly stores Primitive Type data. For other Primitive Type other than Boolean, there is a corresponding Buffer subclass, bytebuffer is the most important subclass.
The following UML class diagram describes the relationships of classes in java.nio:
Buffer
A container interface that can be linearly stored in Primitive Type data is defined. Buffer mainly includes features that are independent of type (byte, char ...). It is worth noting that Buffer and its subclasses are not threads.
Every buffer has the following properties:
Capacity This buffer can put most data. Capacity is typically specified when Buffer is created. The read and write operations of LIMIT on Buffer cannot have a subscript. When writing data into the buffer, Limit is generally equal to CAPACITY. When reading data, Limit represents the length of valid data in the buffer. Position Read / write the current subscript. When read / write operations in the relative position of the buffer, the read / write will be submitted from this subscript, and the buffer will update the value of the subscript after the operation is completed. Mark is a temporary storage location. Calling Mark () Sets the Mark as the current position value, and then calls reset () set the position property to the value of Mark. The value of Mark is always less than or equal to the value of the position. If the position of the position is smaller than the mark, the current Mark value will be abandoned.
These attributes always meet the following conditions: 0 <= Mark <= position <= limited <= Capacity
The value of LIMIT and POSITION is set by the limit () and position () functions, or by the following functions:
Buffer clear () Set the position to 0, set the LIMIT to Capacity, which is generally called before the data is written to buffer. Buffer flip () Set Limit to the current position, set the position to 0, generally calling from the buffer read data. Buffer rebed () Set the position to 0, Limit does not change, generally resend data to Buffer forward. Buffer objects may be read-only. At this time, any write operation to this object triggers a readOrthlyBuffeRexception. IsReadOnly () method can be used to determine if a buffer is read only.
Bytebuffer
In the subclass of Buffer, Bytebuffer is a particularly special class because various Channel IO operations defined in java.io.channels are basically expanded around bytebuffer.
Bytebuffer defines 4 static methods to create creation:
Bytebuffer Allocate (int Capacity) Creates a Bytebuffer specified by Capacity. Bytebuffer AllocateDirect (int Capacity) Creates a Direct's Bytebuffer, which is better when participating in IO operations (it is very likely to implement DMA technology at the underlying implementation), corresponding, create, and reclaim Direct's Bytebuffer price Also high. The isDirect () method can check if a buffer is Direct. Bytebuffer Wrap (Byte [] Array) Bytebuffer Wrap (byte [] Array, Int Offset, INT Length Packs a part of the Byte array or Byte array into a Bytebuffer.
Bytebuffer defines a series of GET and PUT operations to read and write BYTE data, as follows:
Byte get () bytebuffer get (byte [] dst) BYTE GET (INT INDEX)
Bytebuffer Put (byte b) bytebuffer put (byte [] src) Bytebuffer Put (int index, byte b)
These operations can be divided into absolute positioning and relatively definitely two, relatively positioned read and write operations depending on the position to locate the position in the buffer, and update the Position value after the operation is completed. In other types of buffers, the same functions are also defined to read and write data, and the only difference is some parameters and returns.
In addition to reading and writing Byte type data, a specialty of bytebuffer is that it also defines how to read and write other Primitive data, such as:
INT getint () reads an int value from the Bytebuffer. Bytebuffer Putint (int value) writes an int value to bytebuffer.
Reading and writing other types of data involves the word sequence problem, bytebuffer is written or read in its word sequence (large character sequence or small character sequence) or reads out one other type of data (INT, long ...). The byte sequence can be obtained and set by the Order method:
BYTEORDER ORDER () Returns the byte order of ByTeBuffer. Bytebuffer Order (Byteorder Bo) Sets the byte order of ByTeBuffer.
Another special place byTetebuffer is to get other types of buffers on its basis. Such as:
Charbuffer AscharBuffer () Creates a view of a Charbuffer for current Bytebuffer. The read and write operation in this view buffer acts on the Bytebuffer in the byte sequence in the byte sequence of ByteBuffer. The buffer created with this type of method will start from the position position of Bytebuffer to the LIMIT position, which can be seen as a view of this data. View Buffer's readOONLY attributes and Direct properties are consistent with ByTeBuffer, and only the Direct Buffer of other data types can only be obtained in this way.
Byteorder
The class used to represent the ByTeBuffer word sequence can view it into the Enum type in Java. It mainly defines the following static methods and properties:
Byteorder Big_endian represents the ByteORDER of the big character. Byteorder Little_endian represents the Byteorder of the small character sequence. Byteorder NativeORDER () Returns the byte order of the current hardware platform.
Mappedbytebuffer
Bytebuffer subclass, is a mapping of file content in memory. An example of this class needs to be created via the FileChannel's MAP () method.
Next, look at an example of using ByTeBuffer, this example is constantly read from the standard input, and after reading a line, write the collected characters to the standard output:
Public static void main (string [] args)
Throws oException
{
// Create a capacity to 256 Bytebuffer
Bytebuffer buf = bytebuffer.allocate (256);
While (true) {
/ / Read a character from the standard input stream
INT c = system.in.read ();
// When reading the input stream, exit the loop
IF (c == -1)
Break;
// Write the read characters in Bytebuffer
BUF.PUT (BYTE) C);
// When reading a line, the result is collected.
IF (c == '/ n') {
// Call FLIP () Make Limit to the current position value, Position changes to 0,
/ / Read from Bytebuffer to the next
BUF.FLIP ();
// Build an array of BYTE
BYTE [] Content = New byte [buf.limit ()];
/ / Read data from Bytebuffer to the Byte array
BUF.Get (Content);
// Write the contents of the BYTE array to the standard output
System.out.print (New String (Content));
// Call clear () makes the position becomes 0, the limit changes to Capacity,
/ / Write the data to the Bytebuffer to prepare
BUF.CLEAR ();
}
}
}
Package java.nio.channels
This package defines the concept of Channel, and Channel shows a channel that can be performed (for example, through FileChannel, we can read and write files). Java.nio.Channels contains the file system and network communication-related Channel class. This package also defines an API that performs non-blocking IO operations by Selector and SelectableChannel, which is very important for applications that require high performance IO.
The following UML class diagram describes the relationship of Interface in java.nio.channels: Channel Channel represents a channel that can be performed, which defines the following methods:
Boolean isopen () This Channel is open. Void Close () Close this Channel, the relevant resource will be released.
ReadableBytechannel
Define a Channel Interface that can read byte data from it.
INT Read (Bytebuffer DST) reads Byte data from the Channel and writes in Bytebuffer. Returns the number of BYTEs read.
WritablebyTechannel
Define a Channel Interface that can write Byte data.
INT WRITE (Bytebuffer SRC) reads Byte data from Bytebuffer and writes in the Channel. Returns the number of writes written.
Bytechannel
Bytechannel does not define a new method, its role is just to combine ReadableByTechannel and WritableByTechannel.
ScatteringBytechannel
Inherited ReadableByTechannel and provides the ability to write data in several bytebuffers.
GatheringBytechannel
Inherited WritableBytechannel and provides the ability to read data from several ByteBuffers.
InterruptibleChannel
It is used to show channel of Channel that can be closed asynchronously. This is manifested in two aspects: 1. When an InterruptibleChannel's Close () method is called, other Block will receive an AsynchronousCloseException on this InterruptibleChannel IO operation. 2. When a thread block is operated on the IO of InterruptibleChannel, another thread calls the thread's interrupt () method that causes Channel to be closed, the thread receives a ClosedByInterrupTexception, and the thread's Interrupt status will be set.
The next UML class diagram describes the relationship between java.nio.channels:
Non-blocking IO
Non-blocking IO support can be considered the most important feature in the NIO API. Non-blocking IO allows applications to simultaneously monitor multiple Channel to improve performance, this feature is achieved by Selector, SelectableChannel, and SelectionKey.
SelectableChannel represents Channel that can support non-blocking IO operations, which can be registered on Selector, which is manifested by SelectionKey (see UML map). Selector This class provides an application for the application to simultaneously monitor multiple IO Channel:
The application is called by calling the select () function, allowing the Selector to register multiple SelectableChannel, when there is a CHANNEL's IO operation, the select () method will return to check the status of the CHANEL, and make the corresponding Treatment.
Below is an example of Non-blocking IO in JDK 1.4, this Code uses Non-blocking IO to implement a Time Server:
Private static void acceptconnections (int port) throws exception {
// Open a Selector
Selector AcceptSelector =
SelectorProvider.Provider (). OpenSelector ();
// Create a ServersocketChannel, this is a subclass of SELECTABLECHANNEL
ServersocketChannel SSC = ServersocketChannel.Open ();
// Set it to a non-blocking state so that non-blocking IO operations can be performed
Ssc.configureblocking (false);
// Bind IP and ports for the Socket corresponding to ServersocketChannel
Inetaddress lh = inetaddress.getlocalhost ();
Inetsocketaddress isa = new inetsocketaddress (lh, port);
Ssc.socket (). Bind (ISA);
// Register ServerSocketChannel to Selector and return to the corresponding SelectionKey
SelectionKey AcceptKey =
Ssc.register (AcceptSelector, SelectionKey.op_Accept);
INT keysadded = 0;
// Use the select () function to monitor the SELECTABECHANNEL registration on Selector
// The return value represents how many Channel can perform IO operation (Ready for IO)
While (KeySadded = AcceptSelector.select ())> 0) {
// selectedKeys () returns a collection of SelectionKey,
// The SelectionKey represents a Channel that can perform IO operations.
// A ServersocketChannel can perform IO operation means that there is a new TCP connection.
SET ReadyKeys = AcceptSelector.SelectedKeys ();
Iterator I = ReadyKeys.Itemrator ();
While (I.hasNext ()) {
SelectionKey SK = (SelectionKey) i.next ();
// Need to remove the processed key from SelectedKeys
I.Remove ();
// Get the corresponding Channel from SelectionKey
ServersocketChannel NextReady =
(Serversocketchannel) sk.channel ();
// Accept a new TCP connection
Socket s = nextReady.accept (). Socket ();
// Write the current time to this new TCP connection
PrintWriter out =
New PrintWriter (s.getoutputStream (), true);
Date now = new date ();
OUT.PRINTLN (NOW);
// Close connection
Out.close ();
}
}
} This is a pure example, because only one ServerSocketChannel needs to monitor, so do not really need to use non-block IO. However, it is because of its simple, it can be easily seen how non-blocking IO works.
SelectableChannel
This abstraction is the parent class that supports Channel (such as DataGramChannel, SocketChannel) supporting non-blocking IO operations. SelectableChannel can be registered to one or more Selectors to perform non-blocking IO operations.
SelectableChannel can be Blocking and Non-Blocking mode (all Blocking mode when all CHANNEL is created), only Non-Blocking SelectableChannel can participate in non-blocking IO operations. SelectableChannel ConfigureBlocking (Boolean Block) Sets the Blocking mode. Boolean isblocking () Returns Blocking mode.
Through the register () method, SelectableChannel can be registered on the Selector.
INT Validops () returns a Bit Mask that represents the IO operations supported on this Channel. Currently in SelectionKey, four IO operations are defined with static constants: op_accept, op_connect, op_read, and op_write. SelectionKey Register (Selector SEL, INT OPS) Registers the current Channel to a Selector and returns the corresponding SelectionKey. After this, you can monitor this CHANNEL by calling the Select () function of the Selector. The parameter of the OPS is a bit master, which represents the IO operation that needs to be monitored. SelectionKey Register (Selector Sel, Int Ops, Object Att) This function is the same as the last meaning, and more ATT parameters are stored as Attachment in the returned SelectionKey, which is useful when you need to store some Session State. Boolean IsRegistered () This Channel is registered on one or more Selectors.
SelectableChannel also provides a method for obtaining corresponding SelectionKey:
SelectionKey Keyfor (Selector SEL) Returns SelectionKey corresponding to the registration relationship of the CHANNE on Selector. Returns NULL if there is no registration.
Selector
Selector can simultaneously monitor the IO status of multiple SelectableChannel, which is the core of non-blocking IO.
Selector Open () Selector's static method for creating an instance.
In a Selector, there are 3 SelectionKey collections: 1. The key set represents all the Channel registered on this Selector, which can be taken through the keys () method. 2. Selected-key set represented all Channel, which can be monitored by select () method, which can be obtained by SelectEdKeys (). 3. The CancelleD-Key Set represents Channel Cancel's registration relationship, in the next SELECT () operation, these Channel corresponding to SelectionKey will be moved from the key set and Cancelled-KEY SET. This collection cannot be accessed directly.
The following is a description of the select () related method:
INT select () Monitors all registered Channel, when there is a registered IO operation, the function returns, and adds the corresponding SelectionKey to the Selected-Key Set. INT SELECT (long timeout) can set the timeout SELECT () operation. INT Selectnow () makes a SELECT () operation returned immediately. Selector Wakeup () makes a SELECT () operation that has not been returned immediately returns. SelectionKey
Represents Selector and SelectableChannel registration relationships.
Selector defines four static constants to represent four IO operations, which can be combined into a bit Mask.
INT op_accept has a new network connection to Accept, ServersocketChannel supports this non-blocking IO. INT OP_CONNECT represents the connection has been established (or error), and SocketChannel supports this non-blocking IO. INT op_read int op_write represents a read, write operation.
The following is the main method:
Object attachment () Returns the attackKey Attachment, Attachment can specify when registering CHANNEL. Object Attach (Object OB) Sets SelectionKey Attachment. SelectableChannel Channel () Returns the Channel of the SelectionKey. Selector selector () Returns the SelectionKey corresponding to the Selector. Void Cancel () Cancel This registration relationship corresponds to the SelectionKey. INTERESTOPS () Returns bit mask representing IO operations that requires Selector monitored. SelectionKey Interestops (INT OPS) Sets Interestops. Int Readyops () Returns a Bit Mask that represents the IO operation that can be performed on the corresponding CHANNEL.
ServersocketChannel
Support for non-blocking operations, corresponding to Java.Net.Serversocket, provides the TCP protocol IO interface, supporting OP_ACCEPT operations.
ServerSocket Socket () Returns the corresponding Serversocket object. SocketChannel Accept () accepts a connection and returns the SocketChannel object that represents this connection.
SocketChannel
Supports non-blocking operations, corresponding to Java.Net.Socket, provides TCP protocol IO interface, support op_connect, op_read, and op_write operations. This class also implements the Bytechannel, ScatteringBytechannel and GatheringBytechannel interfaces. DataGramChannel and this class are similar, which corresponds to java.net.datagramsocket, which provides UDP protocol IO interfaces.
Socket Socket () Returns the corresponding socket object. Boolean Connect (SocketAddress Remote) Boolean FinishConnect () Connect () performs a connection operation. If the current SocketChannel is Blocking mode, this function will return to the connection operation or error occurrence. If the current SocketChannel is a Non-Blocking mode, the function returns TRUE when the connection can be established, otherwise the function returns false, the application needs to use the FinishConnect () method to complete the connection operation. Pipe
A read and a written Channel (Pipe.SourceChannel and Pipe.sinkChannel), which can be used in the process of communication.
FileChannel
Used to read, write, mapping, lock, etc. And mapping operations related to FileChannel.mapmode, and lock operations related classes have FILELOCK. It is worth noting that FileChannel does not support non-blocking operations.
Channels
This class provides a series of Static methods to support interoperability between the Stream class and the CHANNEL class. These methods can be packaged for the CHANNEL class as a Stream class. For example, the ReadableByteChannel is packaged to InputStream or Reader; you can also pack the Stream class to a Channel class, such as the OutputStream package to WritableBytechannel.
Package java.nio.charset
This package defines Charset and corresponding Encoder and Decoder. Below this UML class diagram describes the relationship of this package, you can understand the CHARSET, CHARSETDECODER, and CHARSETENCODER to an Implementation of an Abstract Factory mode:
Charset
Represents a character set while providing Factory Method to build the corresponding CharsetDecoder and CharsetEncoder.
Charset provides the following Static methods:
SortedMap Availablecharsets () Returns all CHARSET objects supported by the current system, using the name of Charset as a set of Key. Boolean Issupported (String CharsetName) Determines whether the name corresponding to the name is supported by the current system. Charset Forname (String CharsetName) Returns the CHARSET object corresponding to the name.
More important methods in Charset are:
String name () Returns the specification name of the character set. Set aliases () Returns all aliases of the character set. CharSetDecoder NewDecoder () Creates a decoder corresponding to this charset. CharsetEncoder NewEncoder () Creates an Encoder corresponding to this charset.
CharsetDecoder
The engine that will be decoded to Unicode Character data according to the byte stream encoded by a character set.
The input of CharsetDecoder is Bytebuffer, the output is Charbuffer. Perform decode operations is generally made as follows:
1. Call the ResetDecoder's reset () method. (You can be called for the first time) 2. Call the decode () method 0 to n, set the endofinput parameter to false, telling Decoder to have new data feeds. 3. Call the decode () method last time, set the endofinput parameter to true, telling Decoder all data has been sent. 4. Call the Flush () method of Decoder. Let Decoder have the opportunity to write some internal state to the output of the output. CharsetDecoder reset () Reset Decoder and clear some internal status in the Decoder. CODERRESULT DECODE (BYTEBUFFER IN, Charbuffut) From the Bytebuffler type input Decode as possible bytes, and writes the result to the output of the CharBuffer type. According to the result of DECODE, it may return 3 CODERRESULT: CODERRESULT.UNDERFLOW indicates that no input can decode; CODERRESULT.OVERFLOW indicates that the output is full; other CODERRESULT indicates that there is an error in the DECODE process. According to the result of the return, the application can take corresponding measures, such as increasing input, clearing output, etc., and then call the decode () method again. CODERRESULT FLUSH (Charbuffer Out) Some decoders keep some internal status during Decode, calling this method to make these decoders to write these internal states into the output of the output. Call successfully returns CODERRESULT.UNDERFLOW. If the output is not enough, the function returns CODERRESULT.OVERFLOW, and the application should expand the space of the output Charbuffer and then call the method again. Charbuffer Decode (Bytebuffer in) A convenient method puts content Decode in Bytebuff to a newly created Charbuffer. In this method, the four steps mentioned above are included, so it cannot be used with the first three functions.
There are two errors in the decode process: Malformed-Input CoderResult indicates that the data is incorrect; unmappable-character CODERRESULT indicates that there is data in the input that cannot be decoded into unicode. How to deal with the error in the decode process depends on the setting of the Decoder. For these two errors, Decoder can be set to: 1 by CodingerRraction. Ignore the error 2. Report error. (This can cause the error to occur, the decode () method returns a CODERRESULT that represents the error.) 3. Replace the error, replace the part of the error with the replacement character in Decoder.
Codingerrorction MalformedInputAction () Returns the error handling of Malformed-Input. CharSetDecoder OnMalFormedInput (CodingerrorAction NewAction) Sets the error handling of Malformed-Input. CodingerrorAction unmappablecharacteraction () Returns the error handling of unmappable-character. CharsetDecoder OnunMappableCharacter (CodingerRoction newAction) Sets the error handling of UNMAPPABLE-CHARACTER. String replacement () Returns the replacement string of Decoder. CharsetDecoder ReplaceWith (String NewReplacement) Sets the replacement string of Decoder. CharsetEncoder
The Unicode character data encodes the engine of the byte stream of a specific character set. Its interface is similar to CharsetDecoder.
CODERRESULT
Describe the classes of the ENCODE / DECODE operation result.
CodeResult contains two Static members:
CODERRESULT overflow indicates that the output is full of CODERRESULT Underflow indicates that the input has not been available.
Its main member functions are:
Boolean ISError () Boolean ismalFormed () Boolean isunMappable () Boolean isunderflow () Boolean isunderflow () is used to determine the error described by the CODERRESULT.
INT Length () returns the length of the error, for example, cannot be converted to the byte length of Unicode. Void throwexception () throws an Exception corresponding to this CODERRESULT.
Codingerrorction
A class that represents the error handling method in Encoder / Decoder. It can be seen as an ENUM type. Have the following static properties:
CodingerRortion Ignore ignores errors. CodingerRoRaction Replace replaces the part of the error with the replacement string. CODInGERRORACTION Report reports an error. For different functions, it is possible to return a CODERRESULT-related CODERRESULT, or it is possible to throw a CharacterCodingexception.
References David Flanagan - Java in a Nutshell Author: DaiJiaLin mailto: woodydai@gmail.com
http://blog.9cbs.net/daijiang