In detail before JDK 1.4, Java IO Operations were concentrated in the Java.io package and were based on the streaming synchronization (blocking) API. For most applications, such APIs are easy to use, however, some applications with high performance requirements, especially server applications, often require a more efficient way to process IO. From JDK 1.4, the NIO API is introduced as a buffer-based API that provides asynchronous (non-blocking) IO operations. This article carries on the thorough introduction to it.
The NIO APIs are mainly concentrated in the Java.nio and its subpackages:
Java.nio
Defines a subclass of buffer and its data type. The role of the bytebuffer that is used by classes in Java.nio.channels to perform IO operations is very important.
Java.nio.channels
Defines a series of channel interfaces that process IO and the implementation of these interfaces on file systems and network communications. By selector This class, it also provides a way to perform asynchronous 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 APIs.
Java.nio.charset
Defines a class that handles 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 the existing NiO APIs, and in actual use, we typically only deal with another 3 packages. The 3 packages are described below.
Package Java.nio
This package mainly defines the buffer and its subclasses. Buffer defines a container interface for linearly storing primitive type data. For primitive types other than Boolean, there is a corresponding buffer subclass, and Bytebuffer is one of the most important subclasses.
The following UML class diagram describes the relationships of classes in Java.nio:
Buffer
Defines a container interface that can be primitive type data in a linear location. The buffer mainly contains the type (Byte, char ...). ) unrelated features. It is worth noting that the buffer and its subclasses are not thread-safe.
Each buffer has the following properties:
Capacity
The maximum amount of data this buffer can put. Capacity are typically specified when the buffer is created.
Limit
The read and write operation on the buffer cannot cross the subscript. When writing data to buffer, limit is generally equal to capacity, when reading data, limit represents the length of valid data in buffer.
Position
The current subscript for the read/write operation. When a read/write operation is performed using the relative position of buffer, the read/write is performed from the subscript, and after the operation completes, buffer updates the value of the object.
Mark
A temporary storage position subscript. Calling Mark () will set mark as the current position value, and later call Reset () sets the position property to mark's value. Mark's value is always less than or equal to the position value, and if the value of the position is set to be smaller than mark, the current mark value is discarded.
These properties always meet the following criteria:
0 <= Mark <= position <= limit <= capacity
The values of limit and position are set by the limit () and position () functions, or they can be changed by the following functions:
Buffer Clear ()
Set the position to 0 and set the limit to capacity, which is usually called before the data is written to buffer.
Buffer Flip ()
The limit is set to the current position, and the position is set to 0, which is usually called before the data is read from the buffer.
Buffer Rewind ()
The position is set to 0,limit, which is usually called before the data is rewritten into the buffer.
The buffer object may be read-only, and any write to the object will trigger a readonlybufferexception. The IsReadOnly () method can be used to determine whether a buffer is read-only.
Bytebuffer
In the subclass of buffer, Bytebuffer is a very special class, because the various channel IO operations defined in Java.io.channels are basically spread around the bytebuffer.
Bytebuffer defines 4 static methods for creating work:
Bytebuffer allocate (int capacity)
Creates a bytebuffer that specifies the capacity.
Bytebuffer allocatedirect (int capacity)
Create a direct bytebuffer that bytebuffer better performance when participating in IO operations (most likely at the bottom of the implementation using DMA technology), and correspondingly, the cost of creating and reclaiming direct Bytebuffer is higher. The Isdirect () method can check whether a buffer is direct.
Bytebuffer Wrap (Byte [] array)
Bytebuffer Wrap (Byte [] array, int offset, int length)
Wraps a byte array or part of a byte array into Bytebuffer.
Bytebuffer defines a series of get and put operations from which to read and write byte data, such as the following:
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 relative to two, the relative positioning of the read and write operations rely on position to locate the buffer, and the operation is completed after the update position value.
In other types of buffer, the same function is defined to read and write data, and the only difference is the type of some parameters and return values.
In addition to the function of reading and writing byte data, one of the special bytebuffer is that it also defines methods for reading and writing other primitive data, such as:
int GetInt ()
Reads an int value from the Bytebuffer.
Bytebuffer putint (int value)
Writes an int value into the bytebuffer.
Reading and writing other types of data involves a byte-order problem, and Bytebuffer writes or reads a different type of data (Int,long ...) in its byte order (large byte order or small byte order). )。 The byte sequence can be obtained and set with the order method:
Byteorder order ()
Returns the byte order of the Bytebuffer.
Bytebuffer order (Byteorder Bo)
Sets the byte order of the Bytebuffer.
Another special place for Bytebuffer is to get other types of buffer on its basis. Such as:
Charbuffer Ascharbuffer ()
Creates a Charbuffer view for the current bytebuffer. The read and write operations in the view Buffer Act on the data in the Bytebuffer according to the Bytebuffer byte order.
The buffer created with such a method starts at the position position of the bytebuffer and ends at the limit position, which can be viewed as a view of the data. The readonly and direct properties of view buffer are consistent with the bytebuffer, and only in this way can you get direct buffer of other data types.
Byteorder
The class used to represent the Bytebuffer byte order, which can be viewed as an enum type in Java. The following several static methods and properties are mainly defined:
Byteorder Big_endian
A byteorder that represents a large byte sequence.
Byteorder Little_endian
Represents the byteorder of a small byte sequence.
Byteorder Nativeorder ()
Returns the byte order of the current hardware platform.
Mappedbytebuffer
A subclass of Bytebuffer is a mapping of the contents of a file in memory. An instance of this class needs to be created through the FileChannel map () method.
Let's take a look at an example of using Bytebuffer, which reads the characters from the standard input and writes the collected characters to the standard output when a full line is read:
public static void Main (String [] args)
Throws IOException
{
Create a bytebuffer with capacity 256
Bytebuffer buf = bytebuffer.allocate (256);
while (true) {
Read a character from the standard input stream
int c = System.in.read ();
Exit loop when read to end of input stream
if (c = = 1)
Break
Writes the read characters into the Bytebuffer
Buf.put ((byte) c);
Output collected characters when a row is read
if (c = = ' \ n ') {
Call Flip () to change the limit to the current position value, position to 0,
Prepare for next reading from Bytebuffer
Buf.flip ();
Building a byte array
byte [] content = new Byte[buf.limit ()];
Reading data from Bytebuffer to byte array
Buf.get (content);
Writes the contents of the byte array to the standard output
System.out.print (new String (content));
Call Clear () to make position into a value of 0,limit to capacity,
Prepare for next write data to Bytebuffer
Buf.clear ();
}
}
}
Package Java.nio.channels
This package defines the concept of channel, channel shows a channel that can be IO operated (for example, by FileChannel, we can read and write files). Java.nio.channels contains channel classes related to file systems and network communications. This package, through the two classes selector and Selectablechannel, also defines an API for asynchronous (non-blocking) IO operations, which is important for applications that require high-performance IO.
The UML class diagram below describes the relationship between interface in Java.nio.channels:
Channel
Channel shows an IO-capable channel that defines the following methods: interface
Boolean IsOpen ()
Whether the channel is open.
void Close ()
Close this channel and the associated resources will be released.
Readablebytechannel
Defines a channel interface from which byte data can be read.
int read (Bytebuffer DST)
Reads the byte data from the channel and writes it to the Bytebuffer. Returns the number of bytes read.
Writablebytechannel
Defines a channel interface that can write byte data to it.
int write (Bytebuffer src)
Reads the byte data from the Bytebuffer and writes it to the channel. Returns the number of bytes written.
Bytechannel
Bytechannel does not define a new method, its role is to merge Readablebytechannel and Writablebytechannel together.
Scatteringbytechannel
Inherits the Readablebytechannel and provides the ability to write data to several bytebuffer at the same time.
Gatheringbytechannel
Inherits Writablebytechannel and provides the ability to read data from several bytebuffer at the same time.
Interruptiblechannel
Used to represent a channel that can be closed asynchronously. This is manifested in two ways:
1. When a Interruptiblechannel close () method is invoked, the threads of other blocks on this interruptiblechannel IO operation receive a asynchronouscloseexception.
2. When one thread block is on a interruptiblechannel io operation, another thread calls the thread's interrupt () method to cause the channel to be closed, and the thread receives a closedbyinterruptexception , the interrupt state of the thread is set.
The next UML class diagram describes the relationships of classes in Java.nio.channels:
Asynchronous IO
Asynchronous IO support can be considered as the most important feature of the NIO API, which allows applications to monitor multiple channel simultaneously to improve performance, a feature that is implemented through the 3 classes of Selector,selectablechannel and Selectionkey.
Selectablechannel represents a channel that can support asynchronous IO operations and can be registered on selector, which is represented by the Selectionkey class (see UML diagram). Selector This class uses the Select () function to provide an application with a way to monitor multiple IO channel at the same time:
By invoking the Select () function, the application lets selector monitor multiple selectablechannel registered on it, and when a channel IO operation is available, the Select () method returns to allow the application to check the channel state. and make the corresponding treatment.
The following is an example of asynchronous IO in JDK 1.4, which uses asynchronous IO to implement a time server:
Use the Select () function to monitor the Selectablechannel registered on the selector
The return value represents how many channel can be IO operated (ready for IO)
while ((keysadded = Acceptselector.select ()) > 0) {
Selectedkeys () returns a collection of Selectionkey,
Each of these selectionkey represents a channel that can perform IO operations.
A Serversocketchannel io operation means that a new TCP connection is connected to the
Set Readykeys = Acceptselector.selectedkeys ();
Iterator i = Readykeys.iterator ();
while (I.hasnext ()) {
Selectionkey SK = (Selectionkey) i.next ();
You need to remove the handled key from the Selectedkeys collection
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 purely illustrative example, because only one serversocketchannel needs to be monitored, so it really doesn't need to use asynchronous IO. But just because it's simple, it's easy to see how asynchronous IO Works.
Selectablechannel
This abstract class is the parent class for all channel (such as Datagramchannel, Socketchannel) that support asynchronous IO operations. Selectablechannel can be registered on one or more selector for asynchronous IO operations.
Selectablechannel can be blocking and non-blocking modes (all channel are created in blocking mode), Only non-blocking Selectablechannel can participate in asynchronous IO operations.
Through the Register () method, Selectablechannel can be registered on the selector.
int Validops ()
Returns a bit mask that represents the IO operation supported on this channel. Currently in Selectionkey, the bit values of 4 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 on a selector and returns the corresponding Selectionkey. After that, you can monitor the channel by calling the selector select () function. The OPS parameter is a bit mask that represents IO operations that need to be monitored.
Selectionkey Register (Selector sel, int ops, Object att)
This function is the same as the previous one, and the extra att parameters are stored as attachment in the returned Selectionkey, which is useful when you need to store some session state.
Boolean isregistered ()
Whether the channel is registered on one or more selector.
Selectablechannel also provides a way to get the corresponding Selectionkey:
Selectionkey keyfor (Selector sel)
Returns the selectionkey corresponding to the registration relationship of the Channe on selector. Returns null if there is no registered relationship.
Selector
Selector can monitor the IO status of multiple selectablechannel at the same time, which is the core of asynchronous IO.
Selector Open ()
A static method of selector that is used to create an instance.
In a selector, there are 3 sets of Selectionkey:
1. The key set represents all channel registered on this selector, which can be obtained by using the keys () method.
2. Selected-key set represents all channel monitored through the Select () method for IO operations, and this collection can be obtained by Selectedkeys ().
3. The Cancelled-key set represents the channel that has cancel the registration relationship, and in the next select () operation, these channel Selectionkey are removed 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 ()
Monitor all registered channel, when a registered IO operation can be performed, the function returns, and the corresponding Selectionkey is added to the Selected-key set.
int Select (Long timeout)
You can set a select () operation that is timed out.
int Selectnow ()
Make an immediate return select () operation.
Selector Wakeup ()
Causes a Select () operation that has not yet returned returned immediately.
Selectionkey
Represents the registration relationship of selector and Selectablechannel.
The selector defines 4 static constants to represent 4 IO operations, which can be combined to form a bit mask.
int op_accept
There are new network connections that can be accept,serversocketchannel to support this asynchronous IO.
int Op_connect
Represents a connection that has been established (or is an error) and Socketchannel supports this asynchronous IO.
int Op_read
int Op_write
Represents a read and write operation.
The following are the main methods:
Object Attachment ()
The attachment,attachment that returns Selectionkey can be specified when registering channel.
Object Attach (Object OB)
Sets the attachment of the Selectionkey.
Selectablechannel Channel ()
Returns the channel corresponding to the Selectionkey.
Selector Selector ()
Returns the selector corresponding to the Selectionkey.
void Cancel ()
Cancel the registration relation of this selectionkey.
int Interestops ()
Returns the bit mask that represents IO operations that require selector monitoring.
Selectionkey interestops (int ops)
Set Interestops.
int Readyops ()
Returns a bit mask that represents the IO operation that can be performed on the corresponding channel.
Serversocketchannel
Support for asynchronous operations, corresponding to the Java.net.ServerSocket class, provides a TCP protocol IO interface to support op_accept operations.
ServerSocket socket ()
Returns the corresponding ServerSocket object.
Socketchannel Accept ()
Accepts a connection that returns the Socketchannel object that represents the connection.
Socketchannel
Support for asynchronous operations, corresponding to the Java.net.Socket class, provides a TCP protocol IO interface to support Op_connect,op_read and op_write operations. This class also implements the Bytechannel,scatteringbytechannel and Gatheringbytechannel interfaces.
Datagramchannel is similar to this class, and corresponds to the Java.net.DatagramSocket, which provides a UDP protocol IO interface.
Socket socket ()
Returns the corresponding socket object.
Boolean Connect (socketaddress remote)
Boolean Finishconnect ()
Connect () to perform a connection operation. If the current socketchannel is a blocking mode, this function will wait until the connection operation completes or the error occurs before returning. If the current socketchannel is a non-blocking mode, the function returns True if the connection can be created immediately, otherwise the function returns False, and the application needs to use the Finishconnect () method later to complete the join operation.
Pipe
Contains a read and a written channel (Pipe.sourcechannel and Pipe.sinkchannel), which channel can be used for communication in the process.
FileChannel
Used to read, write, map, lock and so on files. The class associated with the mapping operation has Filechannel.mapmode, and the class associated with the lock operation has filelock. It is worth noting that FileChannel does not support asynchronous operations.
Channels
This class provides a series of static methods to support interoperation between the stream class and the Channel class. These methods can wrap the channel class as a stream class, for example, wrap Readablebytechannel as InputStream or reader, or you can wrap the stream class as a channel class, for example, Package the OutputStream as Writablebytechannel.
Package Java.nio.charset
This package defines the charset and corresponding encoder and decoder. The UML class diagram below describes the relationship of the classes in this package and can interpret Charset,charsetdecoder and charsetencoder as an implementation of an abstract factory pattern:
Charset
Represents a character set and provides 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 the key of the set.
Boolean issupported (String charsetname)
Determines whether the character set that corresponds to the name is supported by the current system.
Charset forname (String charsetname)
Returns the CharSet object that corresponds to the name.
The more important methods in CharSet are:
String name ()
Returns the canonical name of the character set.
Set aliases ()
Returns all aliases for this character set.
Charsetdecoder Newdecoder ()
Create a decoder that corresponds to this charset.
Charsetencoder Newencoder ()
Create a encoder that corresponds to this charset.
Charsetdecoder
The engine that decodes a byte stream encoded by some character set to Unicode character data.
The input of Charsetdecoder is Bytebuffer, the output is charbuffer. The following steps are generally performed when decode operations are performed:
1. Call the Reset () method of the Charsetdecoder. (not invoked on first use)
2. Call the Decode () method 0 through N, set the Endofinput argument to False, and tell decoder there is a possibility of new data being fed.
3. The last time the Decode () method is invoked, the Endofinput argument is set to true, telling decoder that all data has been sent.
4. Invokes the decoder flush () method. Let decoder have the opportunity to write some internal state to the output of the Charbuffer.
Charsetdecoder Reset ()
Resets the decoder and clears some of the internal states in the decoder.
Coderresult Decode (Bytebuffer in, Charbuffer out, Boolean endofinput)
Decode as many bytes as possible from the input of the Bytebuffer type and writes the result to the output of the Charbuffer type. According to the results of decode, It is possible to return 3 CoderResult:CoderResult.UNDERFLOW that no input can be decode;coderresult.overflow to indicate that the output is full, and that other coderresult indicate an error occurred in the decode process. Depending on the results returned, the application can take appropriate measures, such as increasing input, clearing output, and so on, and then calling the Decode () method again.
Coderresult Flush (Charbuffer out)
Some decoder will retain some internal state in the decode process, calling this method to give these decoder the opportunity to write these internal states to the charbuffer of the output. The call successfully returned Coderresult.underflow. If there is not enough space for the output, the function returns Coderresult.overflow, when the application should enlarge the space for the output charbuffer and then call the method again.
Charbuffer decode (Bytebuffer in)
A convenient way to decode the contents of Bytebuffer into a newly created charbuffer. The 4 steps mentioned above are included in this method and cannot be used with the first 3 functions.
There are two types of errors in the decode process: Malformed-input Coderresult indicates that the data in the input is incorrect, and Unmappable-character Coderresult indicates that there is data in the input that cannot be decoded into Unicode characters. How you handle errors in the decode process depends on the decoder settings. For both of these errors, decoder can be set by codingerroraction:
1. Ignoring errors
2. Report an error. (This causes an error to occur, the Decode () method returns a Coderresult that represents the error.) )
3. Replace the error, replacing the wrong part with the replacement string in decoder.
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.