Extends worksjava technologytechnical librarymerlin brings nonblocking I/O to the Java platform

Source: Internet
Author: User

a server's ability to handle numerous client requests within a reasonable time is dependent on how to adjust tively it uses I/O streams. A server that caters to hundreds of clients simultaneously must be able to use I/O services concurrently. until JDK 1.4 (aka Merlin), the Java platform did not support nonblocking I/O CILS. with an almost one-to-one ratio of threads to clients, servers written in the Java language were susceptible to enormous thread overhead, which resulted in both performance problems and lack of scalability.

To address this issue, a new set of classes have been introduced to the Java platform with the latest release. merlin's Java. NIO package is chock full of tricks for resolving thread overhead, the most important being the newSelectablechannelAndSelectorClasses.ChannelRepresents a means of communication between a client and a server.SelectorIs analogous to a Windows message loop, in which the selector captures the various events from different clients and dispatches them to their respective event handlers. in this article, we'll show you how these two classes function together to create a nonblocking I/O mechanic for the Java platform.

I/O programming before Merlin

We'll start with a look at a basic, pre-Merlin server-socket program. In the lifetime ofServersocketClass, the important functions are as follows:

    • Accept incoming connections
    • Read requests from clients
    • Service those requests

Let's take a look at each of these steps using code snippets to define strate. First, we create a newServersocket:

Serversocket S = new serversocket ();

Next, we want to accept an incoming call. A callAccept ()Shocould do the trick here, but there's a little trap you have to watch:

Socket conn = S. Accept ();

The callAccept ()Blocks until the server socket accepts a client request for connection. Once a connection is established, the server reads the client requests, usingLinenumberreader. BecauseLinenumberreaderReads data in chunks until the buffer is full, the call blocks on a read. The following snippet showsLinenumberreaderIn action (blocks and all ).

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 to read data. Unfortunately,ReadMethod also blocks until data is available, as doesWriteMethod.

Figure 1 depicts the typical workings of a server. The bold lines represent blocking operations.

Figure 1. A typical server in action

Prior to JDK 1.4, liberal use of threads was the most typical way of getting around blocking. but this solution created its own problem -- namely thread overhead, which impacts both performance and scalability. with the arrival of Merlin and the java. NIO package, however, everything has changed.

In the sections that follow, we'll look at the foundations of Java. NiO, and then apply some of what we 've learned to revising the server-socket example described above.

Back to Top

The reactor Pattern

The principal force behind the design of NiO is the reactor design pattern. server applications in a distributed system must handle multiple clients that send them service requests. before invoking a specific service, however, the server application must demultiplex and dispatch each incoming request to its corresponding service provider. the reactor pattern serves precisely this function. it allows event-driven applications to demultiplex and dispatch service requests, which are then delivered concurrently to an application from one or more clients.

Core functions of the reactor Pattern
    • Demultiplexing events
    • Dispatching events to their corresponding event handlers

The reactor pattern is closely related to the observer pattern in this aspect: All dependents are informed when a single subject changes. the observer pattern is associated with a single source of events, however, whereas the reactor pattern is associated with multiple sources of events.

See resources to learn more about the reactor pattern.

Back to Top

Channels and selectors

NIO's nonblocking I/O mechanic is built aroundSelectorsAndChannels.ChannelClass represents a communication mechanic between a server and a client. In keeping with the reactor pattern,SelectorClass is a multiplexorChannelS. It demultiplexes incoming client requests and dispatches them to their respective request handlers.

We'll look closely at the respective functions ofChannelClass andSelectorClass, and at how the two work together to create a nonblocking I/O implementation.

What the channel does

A channel represents an open connection to an entity such as a hardware device, a file, a network socket, or a program component that is capable of parameter Ming one or more distinct I/O operations, such as reading or writing. NIO channels can be asynchronously closed and interrupted. so, if a thread is blocked in an I/O operation on a channel, another thread can close that channel. similarly, if a thread is blocked in an I/O operation on a channel, another thread can interrupt that blocked thread.

Figure 2. class hierarchy for Java. NiO. Channels

As figure 2 shows, there are quite a few Channel interfaces in the Java. NiO. Channels package. We're mainly concerned withJava. NiO. channels. socketchannelAndJava. NiO. channels. serversocketchannelInterfaces. These channels can be treated as replacementsJava.net. SocketAndJava.net. serversocket, Respectively. channels can be used in a blocking or a nonblocking mode, though of course we will focus on using channels in nonblocking mode.

Creating a nonblocking Channel

We have two new classes to deal with in order to implement basic nonblocking socket read and write operations. These areInetsocketaddressClass from the java.net package, which specifies where to connect to, andSocketchannelClass from the java. NiO. Channels package, which does the actual reading and writing operations.

The code snippets in this section show a revised, nonblocking approach to creating a basic server-socket program. note the changes between these code samples and those used in the first example, starting with the addition of our two new classes:

String host =...; inetsocketaddress socketaddress = new inetsocketaddress (host, 80); socketchannel channel = socketchannel. open (); Channel. Connect (socketaddress );

The role of the buffera is an abstract class that contains data of a specific primitive data type. it is basically a wrapper around und a fixed-size array with getter/setter methods that make its contents accessible. the Buffer Class has a number of subclasses, as follows:

    • Bytebuffer
    • Charbuffer
    • Doublebuffer
    • Floatbuffer
    • Intbuffer
    • Longbuffer
    • Protocol Buffer

BytebufferIs the only class that supports Reading and Writing from and to the other types, since the other classes are type specific. Once connected, data can be read from or written to the channel withBytebufferObject. See resources to learn more aboutBytebuffer.

To make the channel nonblocking, we callConfigureblockingmethod (false)On the channel, as shown here:

Channel. configureblockingmethod (false );

In blocking mode, a thread will block on a read or a write until the operation is completely finished. if during a read, data has not completely arrived at the socket, the thread will block on the read operation until all the data is available.

In nonblocking mode, the thread will read whatever amount of data is available and return to perform other tasks. IfConfigureblockingmethod ()Is passed true, the channel's behavior will be exactly the same as that of a blocking read or write onSocket. The one major difference, mentioned above, is that these blocking reads and writes can be interrupted by other threads.

TheChannelAlone isn' t enough to create a nonblocking I/O implementation.ChannelClass must work in conjunction withSelectorClass to achieve nonblocking I/O.

What the selector does

TheSelectorClass plays the role ofReactorIn the reactor pattern scenario.SelectorMultiplexes events on severalSelectablechannels. EachChannelRegisters events withSelector. When events arrive from clients,SelectorDemutliplexes them and dispatches the events to the correspondingChannelS.

The simplest way to createSelectorIs to useOpen ()Method, as shown below:

Selector selector = selector. open ();

Channel meets Selector

EachChannelThat has to service client requests must first create a connection. The code below createsServersocketchannelCalledServerAnd binds it to a local port:

Serversocketchannel serverchannel = serversocketchannel. open (); serverchannel. configureblocking (false); inetaddress IA = inetaddress. getlocalhost (); inetsocketaddress ISA = new inetsocketaddress (IA, Port); serverchannel. socket (). BIND (ISA );

EachChannelThat has to service client requests must next register itself withSelector.ChannelShocould be registered according to the events it will handle. For instance,ChannelThat accepts incoming connections shoshould be registered as shown here:

Selectionkey acceptkey = channel. Register (selector, selectionkey. op_accept );

AChannel'S registry withSelectorIs represented bySelectionkeyObject.KeyIs valid until one of these three conditions is met:

    • TheChannelIs closed.
    • TheSelectorIs closed.
    • TheKeyItself is canceled by invoking itsCancel ()Method.

TheSelectorBlocks onSelect ()Call. It then waits until a new connection is made, another thread wakes it up, or another thread interrupts the original blocked thread.

Registering the server

ServerIsServersocketchannelThat registers itself withSelectorTo accept all incoming connections, as shown here:

Selectionkey acceptkey = serverchannel. Register (SEL, selectionkey. op_accept); While (acceptkey. selector (). Select ()> 0 ){......

AfterServerIs registered, we iterate through the set of keys and handle each one based on its type. After a key is processed, it is removed from the list of ready keys, as shown here:

Set readykeys = SEL. selectedkeys (); iterator it = readykeys. iterator (); While (it. hasnext () {selectionkey key = (selectionkey) it. next (); it. remove ();............}

If the key is acceptable, the connection is accepted and the channel is registered for further events such as read or write operations. if the key is readable or writable, the server indicates it is ready to read or write data on its end:

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, RET) ;}} if (key. iswritable () {system. out. println ("writable key"); string ret = readmessage (key); socket = (socketchannel) Key. channel (); If (result. length ()> 0) {writemessage (socket, RET );}}

Back to Top

Abracadabra -- nonblocking server socket appear!

The final part of this introduction to nonblocking I/O in JDK 1.4 is left to you: running the example.

In this simple nonblocking server-socket example, the server reads a file name sent from the client, displays the file contents, and writes the contents back to the client.

Here's what you need to do to run the example:

    1. Install JDK 1.4 (see resources ).

    2. Copy both source files onto your directory.
    3. Compile and run the serverJava nonblockingserver.
    4. Compile and run the clientJava client.
    5. Input the name of a text or Java file in the directory where the class files are present.
    6. The server will read the file and send its contents to the client.
    7. The client will print out the data already ed from the server. (Only 1024 bytes will be read since that is the limit ofBytebufferUsed .)
    8. Close the client by entering the command to quit or shutdown.

Back to Top

Conclusion

The new I/O packages from Merlin cover a broad scope. The major advantage of Merlin's new nonblocking I/O implementation is twofold: threads no longer block on reads or writes andSelectorIs able to handle multiple connections, greatly cing server application overhead.

We have highlighted these two primary advantages of the new java. Nio package. We hope that you will apply what you 've learned here to your real-time application development efforts.

Back to Top

Download

Name Size Download Method
J-javaio.zip 3kb HTTP

Information about download Methods

Related Article

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.