Java AIO Learning

Source: Internet
Author: User
Tags readable throwable

Reprint the contents of reactor and Proactor

System I/O can be divided into blocking type, non-blocking synchronous type and non-blocking asynchronous type [1, 2]. Blocking I/O means that control is not returned to the caller until the call operation is finished. As a result, the caller is blocked, and there is no other thing to do during that time. Even more depressing, it's a waste of resources for the caller to be able to respond to other requests at this time while waiting for IO results. In the case of Read (), the code that calls this function freezes here until data arrives in the socket cache it reads.

In contrast, non-blocking synchronization returns control to the caller immediately. The caller does not need to wait, it obtains two results from the function being invoked: either the call succeeds or the system returns an error identity that tells the caller that the current resource is not available, you can wait or try again. For example, the read () operation, if the current socket is countless readable, then immediately return to Ewoulblock/eagain, tell the call to read () "The data is not ready, you will try again later."

In non-blocking asynchronous calls, slightly different. When the call function returns immediately, it also tells the caller that the request has already begun. The system uses additional resources or threads to complete this invocation and to notify the caller (for example, through a callback function) when it completes. With Windows ReadFile ( ) or POSIX aio_read () , the function returns immediately after it is invoked, and the operating system starts reading at the same time in the background.

In the above three IO forms, non-blocking asynchrony is the most performance and scalability.

This article explores different I/O utilization mechanisms and provides a cross-platform design pattern (solution). It is hoped that this article can give some help to TCP High-performance server developers to choose the best design scheme. Below we will compare Java, C #, C + + respectively to explore the implementation of the scheme and performance. We stopped talking about blocking scenarios later in the article because blocking I/O is really a lack of scalability and performance is not up to the requirements of high-performance servers.

Two IO multiplexing scenarios: Reactor and Proactor

In general, the I/O multiplexing mechanism requires event Demultiplexor [1, 3]. The role of event-sharing, will be the source of reading and writing events to the processing of read and write events, like sending a courier downstairs shouting: Who sent something, come and get it. At the beginning, the developer needs to register the event of interest at the handlers and provide the appropriate handler (event) or callback function; The event-sharing device distributes the requested events to these handler or callback functions when appropriate.

The two modes involved in the event-sharing device are called: Reactor and Proactor [1]. The reactor mode is based on synchronous I/O, while the proactor mode is related to asynchronous I/O. In reactor mode, an event separator waits for the state of an event or an application or operation to occur (such as a file descriptor can read or write, or a socket is readable or writable), and the event separator passes the event to a previously registered event handler or callback function, which does the actual read-write operation.

In Proactor mode, an event handler (or a generation initiated by an event separator) directly initiates an asynchronous read-write operation (the equivalent of a request), and the actual work is done by the operating system. When initiated, the parameters to be provided include a buffer for reading data, the size of the data read, or a buffer for storing outgoing data, and the callback function after the request is completed. The event separator learns the request, silently waits for the completion of the request, and forwards the completion event to the appropriate event handler or callback. For example, event handlers on Windows post an asynchronous IO operation (called a overlapped technique), and iocompletion events such as event separators complete [1]. The typical implementation of this asynchronous pattern is based on the underlying asynchronous API of the operating system, so we can call it "system level" or "really" asynchronous, because the specific reads and writes are performed by the operating system.

Give another example to better understand the difference between reactor and proactor two patterns. Here we only focus on the read operation, because the write operation is similar. Here's the reactor approach: an event handler claims that it's interested in reading events on a socket; The event separator waits for the event to occur; When an event occurs, the event separator is awakened, which is responsible for notifying the previous event handler; The event handler receives the message and reads the data on the socket. If necessary, it claims to be interested again in the Read event on the socket, repeating the above steps;

Here's how the true Asynchronous Pattern Proactor is done: The event handler sends a write directly (of course, the operating system must support this asynchronous operation). At this point, the event handler doesn't care about the read event, it just sends a request, and it's haunting the completion event of the write Operation . The handler is very drag, send a command regardless of the specific things, only waiting for someone else (System) to help him to fix the time to give him a word back. The event separator waits for the completion of the Read event (compared with the reactor); When the event separator silently waiting for the completion of things to come, while the operating system has started to work, it read data from the target, put into the buffer provided by the user, and finally notify the incident separator, this thing I finished; event handler prior to notification by event-sharing: The things you ordered are done; The event handler will then find that the data that he wants to read has been obediently placed in the buffer he provided, and he can do whatever he wants. If necessary, the event handler also initiates another write operation as before, as in the previous steps.
The implementation of AIO is already built into JDK 7 and can be referenced in the http://www.iteye.com/topic/472333 analysis of AIO
Let's try an example of Jdk7 Aio.
Server-side Programs


Import java.io.IOException;
Import java.net.InetSocketAddress;
Import Java.nio.ByteBuffer;
Import Java.nio.channels.AsynchronousChannelGroup;
Import Java.nio.channels.AsynchronousServerSocketChannel;
Import Java.nio.channels.AsynchronousSocketChannel;
Import Java.nio.channels.CompletionHandler;
Import java.util.concurrent.ExecutionException;
Import Java.util.concurrent.ExecutorService;


Import java.util.concurrent.Executors;

    public class Echoaioserver {private final int port;
        public static void Main (String args[]) {int port = 8000;
    New Echoaioserver (port);
        public echoaioserver (int port) {this.port = port;
    Listen (); private void Listen () {try {executorservice executorservice = Executors.newcachedthreadpool ()
            ;
            Asynchronouschannelgroup Threadgroup = Asynchronouschannelgroup.withcachedthreadpool (ExecutorService, 1); Try (asynchronousserversocketchannel server = AsynchronousservErsocketchannel.open (Threadgroup)) {Server.bind (new inetsocketaddress (port));

                System.out.println ("Echo Listen on" + port); Server.accept (NULL, New Completionhandler<asynchronoussocketchannel, object> () {final Bytebuffe
                    R Echobuffer = bytebuffer.allocatedirect (1024); public void completed (Asynchronoussocketchannel result, Object attachment) {System.out.println ("W
                        Aiting ... ");
                            try {echobuffer.clear ();
                            Result.read (Echobuffer). get ();
                            Echobuffer.flip ();
                            echo Data Result.write (Echobuffer);
Echobuffer.flip ();
                        System.out.println ("echoed '" + New String (Echobuffer.array ()) + "' to" + result); catch (Interruptedexception | ExEcutionexception e) {System.out.println (e.tostring ());
                                Finally {try {result.close ();
                            Server.accept (null, this);
                            catch (Exception e) {System.out.println (e.tostring ());
                    } System.out.println ("Done ...");
                        @Override public void failed (Throwable exc, Object attachment) {
                    SYSTEM.OUT.PRINTLN ("Server failed:" + exc);

                }
                });
                try {//wait for ever Thread.Sleep (Integer.max_value);
                catch (Interruptedexception ex) {System.out.println (ex); catch (IOExceptione) {System.out.println (e);
 }
    }
}

Client programs

Import java.net.InetSocketAddress;
Import Java.nio.ByteBuffer;
Import Java.nio.channels.AsynchronousSocketChannel;
Import Java.nio.channels.CompletionHandler;

Import java.util.concurrent.ExecutionException;
    
    public class Echoaioclient {private final Asynchronoussocketchannel client;
    Public Echoaioclient () throws exception{client = Asynchronoussocketchannel.open (); public void Start () throws exception{Client.connect (new inetsocketaddress ("127.0.0.1", 8000), Null,new Co  Mpletionhandler<void,void> () {@Override public void completed (void result, void attachment)
                    {try {client.write (Bytebuffer.wrap ("This is a test". GetBytes ())).
                SYSTEM.OUT.PRINTLN ("Send data to Server");
                catch (Exception ex) {ex.printstacktrace (); } @Override public void failed (Throwable exc, void Attachment) {exc.printstacktrace ();
        }
        });
        Final Bytebuffer BB = bytebuffer.allocate (1024); Client.read (BB, NULL, New Completionhandler<integer,object> () {@Override public void completed (Integer result
			     , Object attachment) {System.out.println (result);
			System.out.println (New String (Bb.array ()));
				@Override public void failed (Throwable exc, Object attachment) {exc.printstacktrace ();
        

        
        }
        	}
        );
        try {//wait for ever Thread.Sleep (Integer.max_value);
        catch (Interruptedexception ex) {System.out.println (ex);
    } public static void Main (String args[]) throws exception{new Echoaioclient (). Start (); }
}

After executing server and client, the output is as follows:
Server output:

Echo Listen on 8000
waiting ....
Done ...

Client output:

Send data to server
-
a test


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.