Merlin brings non-blocking I / O to the Java platform
English original
content:
Merlin previous I / O programming reactor mode channel and selector 唵 唵 唵 吽 - Non-block I / O! Conclusion Reference Information About the author's evaluation of this article
related information:
Java Design Patterns 101Java Sockets 101magic with merlin
In the Java area:
Teaching tools and product code and components all articles practical skills
New features significantly reduced thread overhead aruna kalagnanam (kaaruna@in.ibm.com), software engineer, IBALU G (GBALU@in.ibm.com), software engineer, IBM 2002 March
The Java technology platform has long been providing a non-blocking I / O mechanism. Fortunately, Merlin (JDK 1.4) has a wand that is applicable in various occasions, and the blocking state of the released I / O is the expertise of this magician. Software Engineers Aruna Kalagnanam and Balu G introduce this non-blocking feature of Merlin, Java.Nio (NIO), and use a socket programming example to show you what NIO can do. Please click on the top or bottom of this article
Discussion, in
Discussion Forum and Author and other readers share your experience in this article.
The ability to handle a large number of client requests within a reasonable time depends on the efficiency of the server using I / O stream. At the same time, servers who provide services to hundreds of clients must be able to use I / O services in concurrently. The Java platform is not allowed to support non-blocking I / O calls until JDK 1.4 (which is Merlin). The server written in Java is almost one-to-one than the ratio of its thread and the client. In order to solve this problem, the latest release of the Java platform introduces a new set of classes. Merlin's Java.NIO package is full of skills to solve threads, the most important thing is the new SelectableChannel class and Selector class. Channel is a communication method between the client and the server. Selector is similar to the Windows message loop, which captures various events from different clients and assigns them to the appropriate event handler. In this article, we will show you how these two classes work together to create a non-blocking I / O mechanism for the Java platform. Merlin's I / O Programming We will start from the foundation of Merlin, Merlin, starts with the server-socket program. In the survival of the ServerSocket class, its important features are as follows:
Accept the incoming connection From the client read request to provide services to the request us to find out that each of the above steps, we use the code snippet. First, we create a new Serversocket:
Serversocket S = New Serversocket ();
Next, we have to accept incoming calls. Here, call accept () should be able to complete the task, but there is a small trap you have to be careful:
Socket conn = s.accept ();
The call to Accept () will always be blocked until the server socket accepts a client request for request. Once the connection is established, the server reads the client request using the LINENUMBERREADER. Because LinenumberReader reads data to the buffer, this call is blocked when reading. The following fragment shows LINENUMBERREADER (blocking, etc.) in the work. InputStream in = conn.getinputstream ();
InputStreamReader Rdr = New InputStreamReader (in);
LINENUMBERREADER LNR = New LinenumberReader (RDR);
Request Req = new request ();
While (! REQ.IsComplete ())
{
String s = lnr.readline ();
Req.addline (s);
}
InputStream.read () is another way of reading data. Unfortunately, the read method has to block the data until the data can be used, and the Write method is the same. Figure 1 depicts a typical working process of the server. The black body indicates a blocking operation. Figure 1. The server in a typical work is free to use threads freely in JDK 1.4, which is the most typical approach to processing the blocking problem. But this solution will generate its own problems - that is, thread overhead, thread overhead simultaneously affects performance and scalability. However, with the arrival of Merlin and Java.nio, everything has changed. In the following sections, we will examine the basic idea of java.nio, and then apply some of the knowledge we have learned to modify the server-socket examples described above. Reactor Pattern NiO The cornerstone behind the design is the reactor design mode. Server applications in a distributed system must handle multiple clients that send service requests to them. However, before calling a specific service, the server application must divide each incoming request multi-way division and assign each other service provider. The reactor mode is just suitable for this feature. It allows event-driven applications to distribute the service request multiplex and assigne, and then these service requests are transmitted from one or more clients to the application.
Core function of reactor mode
The event multi-channel division is extremely similar to the observer pattern (OBSERVER PATTERN) in this regard: Observer Pattern is notified when a subject changes. However, the observer mode is associated with a single event source, and the reactor mode is associated with multiple event sources. See the reference information to learn more about reactor mode. The non-blocking I / O mechanism of the channel and selector NIO is built around the selector and channel. The Channel class represents a communication mechanism between servers and clients. Consistent with the reactor mode, the Selector class is the multi-pass multiplexer of the Channel. The Selector class will be sent to the client request multiple wayt and assigne them to their respective request handles. We will carefully examine the functions of the Channel class and the Selector class, and how these two classes work together, create a non-blocking I / O implementation. What channel does the channel indicates an open connection to an entity (eg, hardware devices, files, network sockets, or program components that can perform one or more different I / O operations (eg, read or write). The NIO channel can be turned off and interrupt asynchronously. So, if a thread is blocked on an I / O operation of a channel, then another thread can close this channel. Similarly, if a thread is blocked on an I / O operation of a channel, the other thread can interrupt this blocking thread. Figure 2. The class hierarchy of java.nio.channels is shown in Figure 2, there are many channel interfaces in the java.nio.channels package. We mainly care about Java.Nio.Channel interface and java.nio.channel interface. These two interfaces can be used to replace java.net.socket and java.net.serversocket, respectively. Although we will of course place the attention on the channel in non-blocking, the channel can be used in a blocking method or a non-blocking manner. Creating a non-blocking channel To achieve the basic non-block socket reading and writing, we have to handle two new classes. They are InetSocketAddress classes from java.net packages, which specifies where to connect, and the SocketChannel class from the java.nio.channels package, which performs actual read and write operations. The code snippet in this section shows a modified, non-blocking approach to create a base-socket-socket program. Note that these code samples are changed between the code used in the first example, from adding two new classes: String host = ...;
Inetsocketaddress socketaddress = new inetsocketaddress (Host, 80);
Socketchannel Channel = SocketChannel.Open ();
Channel.connect (socketaddress);
The role buffer of the buffer is an abstract class containing a particular basic data type data. From essentially, it is a wrapper that will be packaged with a fixed size of the getter / setter method, which allows the contents of the buffer to be accessed. There are many subclasses in the Buffer class, as follows:
Bytebuffer Charbuffer Doublebuffer FloatBuffer InTbuffer Longbuffer ShortBuffer Bytebuffer is the only class that supports other types of classes because other classes are specific to type. Once connected, you can use the ByteBuffer object from channel read data or write the data to the channel. See the reference information to learn more about Bytebuffer. In order to make the channel become non-blocking, we call ConfigureBlockingMethod (FALSE) on the channel, as shown below: Channel.configureBlockingMethod (false);
In blocking mode, the thread will block when reading or writing, and has been completely completed until the read or write operation is complete. If it is read, the data has not been fully reached, and the thread will block the read operation, until the data is available. In the non-blocking mode, the thread will read the available data (regardless), and then return to perform other tasks. If true (TRUE) is passed to ConfigureBlockingMethod (), the behavior of the channel will be identical to the behavior that is blocked or written on the socket. The only main difference is as mentioned above, which is that these block read and write can be interrupted by other threads. It is not enough to create a non-blocking I / O at Channel. To achieve non-blocking I / O, the Channel class must work with the Selector class. What does the selector do in the reactor mode scenario, the Selector class acts as a Reactor role. Selector multi-channel is multiplexed for multiple SelectableChannels. Each Channel registers events to the Selector. When the event arrives from the client, Selector divides them multiple times and assigns these events to the corresponding Channel. Creating the easiest way to create a selector is to use the Open () method, as shown below:
Selector selector = selector.open ();
The channel encounters the selector each of the CHANNEL to request a service to the client to first create a connection. The following code creates ServerSocketChannel called Server and binds it to local ports:
ServersocketChannel ServerChannel = ServersocketChannel.Open ();
ServerChannel.configureBlocking (False);
Inetaddress IA = inetaddress.getlocalhost ();
Inetsocketaddress isa = new inetsocketaddress (IA, port);
ServerChannel.Socket (). Bind (ISA);
Each Channel to request a service to serve the client must then register yourself to Selector. Channel should register the events according to it. For example, Channel accepted incoming connection should be registered like this as follows:
SelectionKey AcceptKey =
Channel.Register (Selector, SelectionKey.op_Accept);
Channel is represented by the SelectionKey object to the Selector's registration. Meet one of the following three conditions, Key invals:
Channel is closed. Selector is turned off. Cancel KEY itself by calling the Cancel () method of Key. Selector blocks when select () calls. Then, it starts waiting until a new connection is established, or another thread wakes it, or the other thread will interrupt the original blocking thread. The registration server Server is the serversocketchannel that will be registered with you to accept all incoming connections, as shown below: SelectionKey AcceptKey = ServerChannel.Register (SEL, SelectionKey.op_Accept);
While (AcceptKey.Selector (). SELECT ()> 0) {
......
After Server is registered, we process a group of keywords based on the type of each keyword (key). After a keyword is completed, it is removed from the Ready Keys list, as shown below:
Set readyKeys = SEL.SELECTEDKEYS ();
Iterator it = ReadyKeys.Item ();
While (it.hasnext ())
{
SelectionKey Key = (SelectionKey) IT.Next ();
it.remove ();
....
....
....
}
If the keyword is acceptable, the connection, registration channel is accepted to accept more events (eg, read or write). If the keyword is readable or writable, the server indicates that it has read and write this end data:
SocketChannel Socket;
IF (Key.isacceptable ()) {
System.out.println ("Acceptable Key");
ServersocketChannel SSC = (ServersocketChannel) Key.Channel ();
Socket = (socketchannel) ssc.accept ();
Socket.configureblocking (false);
SelectionKey Another =
Socket.Register (SEL, SelectionKey.op_read | SelectionKey.op_write);
}
IF (Key.IsReadable ()) {
System.out.println ("Readable Key");
String Ret = ReadMessage (key);
IF (Ret.Length ()> 0) {
WriteMessage (socket, re);
}
}
IF (key.iswritable ()) {
System.out.println ("Writable Key");
String Ret = ReadMessage (key);
Socket = (socketchannel) key.channel ();
IF (Result.Length ()> 0) {
WriteMessage (socket, re);
}
}
唵唵 唵 咪 吽 - Non-blocking server socket fast show! The last part of the non-blocking I / O introduction to JDK 1.4 is left to you: run this example. In this simple non-blocking server-socket example, the server reads the file name sent from the client, display the contents of the file, and then write the content back to the client. Here is what you need to do with this example: Install JDK 1.4 (see Resources). Copy the two source code files to your directory. Compile and run the server, Java NonblockingServer. Compile and run clients, Java Client. Enter a text file or a name of the Java file in the directory where the class file is located. The server will read the file and send its content to the client. The client will print out the data received from the server. (Since the ByteBuffer used is limited, only 1024 bytes will be read.) Enter the quit or shutdown command to turn off the client. Conclusion Merlin's new I / O package coverage is very wide. The main advantages of Merlin's new non-blocking I / O implementation have two aspects: threads no longer occurs at read or write, and Selector can handle multiple connections, thereby significantly reduced server application overhead. We have focused on the two advantages of the new Java.nio package. We hope that you will apply the knowledge you have learned here to your actual application development work. Reference
Please click on the discussion forum on top or bottom of this article to participate in this article. Download the source code to run the example of this article. Install JDK 1.4. Learn all new non-blocking I / O APIs on the NIO home page. To learn more about JDK 1.4, see Java 2 Platform, Standard Edition, V1.4 overview. Please visit Java Community Process to learn about the process of java.nio is part of the Java platform. To understand the in-depth discussion of thread overhead issues for the Java platform, see Allen Holub's Proposal for Fixing Problems, some of which discusses Java I / O (developerWorks, October 2000). Learn more about the Bytebuffer class. If you want to learn about design patterns, please read "Java Design Patterns 101" (developerWorks, Jan 2002). Get more information about Reactor Pattern. If you want to learn more about socket programming, please read "Java Sockets 101" (DeveloperWorks, August 2001). John Zukowski's Magic with Merlin column tells the changes caused by Merlin to the Java platform. The article "Master Merlin's New I / O Classes" on JavaWorld tells you how to get the most performance from a non-blocking I / O and memory map buffer. Do you want to explore what choice as a developer? Start with the complete list of Developer Kits from DeveloperWorks. You can find hundreds of articles about Java programming in the developerWorksJava technology area.
About the author Aruna Kalagnanam is a software engineer in IBM India Lab e-commerce integration technology. You can contact Aruna via kaaruna@in.ibm.com. Balu G is a software engineer in IBM India Lab e-commerce integration technology. You can contact Balu via gbalu@in.ibm.com. Page