Netty5 Source Analysis (vii)--Asynchronous execution of future and promise

Source: Internet
Author: User

Java.util.concurrent.Future is a Java-provided interface that represents the state of asynchronous execution, and the Get method of the future will determine whether the task is completed or not, and if it completes, it will block the thread until the task is complete.

Java Futuretask.get () public V get () throws Interruptedexception, executionexception {        int s = State;        if (s <= completing)            s = Awaitdone (false, 0L);        Return report (s);    }

Netty extends the future of Java, the main improvement is to add the listener listener interface, through the listener can make asynchronous execution more efficient, do not need to wait for the end of asynchronous execution through get, but through the listener callback to precisely control the end of the asynchronous execution point in time.

Public interface Future<v> extends Java.util.concurrent.future<v> {boolean issuccess ();    Boolean iscancellable ();    Throwable cause ();    Future<v> AddListener (genericfuturelistener< extends future<? Super V>> Listener);    Future<v> addlisteners (genericfuturelistener< extends future<? super V>> .... listeners);    Future<v> RemoveListener (genericfuturelistener< extends future<? Super V>> Listener);    Future<v> removelisteners (genericfuturelistener< extends future<? super V>> .... listeners);   Future<v> sync () throws interruptedexception;     Future<V> syncuninterruptibly ();    Future<v> await () throws interruptedexception;    Future<v> awaituninterruptibly ();    Boolean await (long timeout, timeunit unit) throws Interruptedexception;    Boolean await (long Timeoutmillis) throws interruptedexception;    Boolean awaituninterruptibly (long timeout, timeunit unit); BooLean awaituninterruptibly (long timeoutmillis);    v Getnow ();  boolean Cancel (Boolean mayinterruptifrunning);}

The Channelfuture interface extends the Netty's future interface, which represents an asynchronous call with no return value, with the channel associated with a channel bound

Public interface Channelfuture extends future<void> {    channel channel ();    @Override    channelfuture AddListener (genericfuturelistener< extends future<? Super Void>> listener);    @Override    channelfuture addlisteners (genericfuturelistener< extends future<? super Void>>.. listeners);    @Override    channelfuture removelistener (genericfuturelistener<? extends Future<? Super Void>> Listener);    @Override    channelfuture removelisteners (genericfuturelistener< extends future<? super Void>>.. listeners);    @Override    channelfuture Sync () throws interruptedexception;    @Override    channelfuture syncuninterruptibly ();    @Override    Channelfuture await () throws interruptedexception;    @Override    channelfuture awaituninterruptibly ();}

The Promise interface also extends the future interface, which represents a writable future that can set the results of asynchronous execution

Public interface Promise<v> extends future<v> {    promise<v> setsuccess (V result);    Boolean trysuccess (V result);    Promise<v> setfailure (throwable cause);    

The Channelpromise interface extends the promise and channelfuture, binds the channel, writes the asynchronous execution structure, and has the listener's function, which is the interface that netty the actual programming used to represent asynchronous execution.


Public interface Channelpromise extends Channelfuture, promise<void> {@Override channel channel ();    @Override channelpromise setsuccess (Void result);    Channelpromise setsuccess ();    Boolean trysuccess ();    @Override channelpromise setfailure (throwable cause);    @Override channelpromise AddListener (genericfuturelistener< extends future<? Super Void>> Listener); @Override channelpromise addlisteners (genericfuturelistener< extends future<? super Void>> .... listeners)    ;    @Override channelpromise RemoveListener (genericfuturelistener< extends future<? Super Void>> Listener); @Override channelpromise removelisteners (genericfuturelistener< extends future<? super Void>> .... listene    RS);    @Override channelpromise Sync () throws interruptedexception;    @Override channelpromise syncuninterruptibly ();    @Override Channelpromise await () throws interruptedexception; @Override channelpromise Awaituninterruptibly ();} 

Defaultchannelpromise is an implementation class for Channelpromise, which is a promoise instance of the actual runtime. The Channel interface provides a newpromise interface that represents the channel to create an asynchronous execution of an action

Public interface Channel extends AttributeMap, comparable<channel> {    channelpromise newpromise ();} Public abstract class Abstractchannel extends Defaultattributemap implements Channel {public    channelpromise    Newpromise () {return new defaultchannelpromise (this); }}

Netty recommends using AddListener to callback the results of asynchronous execution, which is better than Future.get, and allows more precise timing of the end of an asynchronous execution

Take a look at the AddListener method of the Defaultpromise, which determines the state of the asynchronous task execution and, if done, understands the notification listener or joins the listener queue

Notifying listeners is to find a thread to perform the callback function that invokes the listener.

Defaultpromise.addlistenerpublic promise<v> AddListener (genericfuturelistener<? extends Future<?        Super V>> Listener) {if (listener = = null) {throw new NullPointerException ("Listener");            } if (IsDone ()) {Notifylistener (Executor (), this, listener);        return this; } synchronized (this) {if (!isdone ()) {if (listeners = = null) {List                Eners = listener; } else {if (listeners instanceof Defaultfuturelisteners) {(defaultfutureliste                    ners) listeners). Add (listener); } else {@SuppressWarnings ("unchecked") final genericfuturelistener<? ext Ends Future<v>> Firstlistener = (genericfuturelistener<? extends Future<v&gt                        ;>) listeners; Listeners = new Defaultfuturelisteners (firsTlistener, listener);            }} return this;        }} notifylistener (Executor (), this, listener);    return this; }protected static void Notifylistener (            final Eventexecutor Eventexecutor, Final future<?> future, Final genericfuturelistener<?> L) {         if (Eventexecutor.ineventloop ()) {             final Integer stackdepth = Listener_stack_depth.get ();             if (Stackdepth < max_listener_stack_depth) {                 Listener_stack_depth.set (stackdepth + 1);                 Try {                     NotifyListener0 (Future, L);                 finally {                     Listener_stack_depth.set ( stackdepth);               }                 return;            }       }         Try {            Eventexecutor.execute (New Runnable () {                 @Override                  public void Run () {                    NotifyListener0 (Future, L);                }           });         catch (Throwable t) {            Logger.error ( "Failed to notify a listener. Event Loop shut down? ", T);       }   }    @ Suppresswarnings ({"Unchecked", "Rawtypes"})     static void NotifyListener0 (future, Genericfuturelistener l) {        try {             L.operationcomplete (future);       } catch ( Throwable t) {            if (Logger.iswarnenabled ()) {                 Logger.warn ("An exception is thrown by" + L.getclass (). GetName () + ". Operationcomplete ()", T);            }       }    }

Then look at the listener's interface, just a method, that is, after the completion of the asynchronous task execution, get the future result, the execution of the callback logic

Public interface Genericfuturelistener<f extends future<?>> extends EventListener {    void Operationcomplete (F future) throws Exception;}


Take a look at an instance, in the process of server binding, call Initandregister () to create and register the channel.

1. This process first creates an asynchronous task with channel.newpromise and then passes the promise instance to the Register method.

2. Register method to find a thread to execute the Register0 method, the first step is to return the task after handing it over to the thread. This is a process of asynchronous execution

3. In the new thread, set the state of the promise. You can see that promise represents a future that can be written .

4. The original thread resumes execution after getting the result returned by the Initandregister, which is performed by two threads

5. The original thread to determine the status of promise to determine whether the registration is complete, if the registration is completed to perform subsequent doBind0, if not completed, by adding a callback method to execute asynchronously

Final Channelfuture Initandregister () {channel channel;        try {channel = CreateChannel ();        } catch (Throwable t) {return VoidChannel.INSTANCE.newFailedFuture (t);        } try {init (channel);            } catch (Throwable t) {Channel.unsafe (). closeforcibly ();        return Channel.newfailedfuture (t);        } channelpromise regfuture = Channel.newpromise ();        Channel.unsafe (). Register (regfuture);            if (regfuture.cause () = null) {if (channel.isregistered ()) {channel.close ();            } else {Channel.unsafe (). closeforcibly ();      }} because register (), bind (), and connect () is all bound to the same thread.    return regfuture; }<pre name= "code" class= "Java" > Public final void Register (final channelpromise Promise) {if (eventloop.            Ineventloop ()) {Register0 (Promise);           } else {     try {<strong> Eventloop.execute (new Runnable () {@Override                        public void Run () {Register0 (Promise);                            }});</strong>} catch (Throwable t) {Logger.warn (                            "Force-closing a channel whose registration task is not accepted by an event loop: {}",                    Abstractchannel.this, T);                    Closeforcibly ();                    Closefuture.setclosed ();                Promise.setfailure (t); }}} private void Register0 (Channelpromise promise) {try {//Check I  f The channel is still open as it could being closed in the mean time time the register/call was outside of                The EventLoop if (!ensureopen (Promise)) {return;             }   Doregister ();                Registered = TRUE;                Promise.setsuccess ();                Pipeline.firechannelregistered ();                if (isActive ()) {pipeline.firechannelactive ();                }} catch (Throwable t) {//Close the channel directly to avoid FD leak.                Closeforcibly ();                Closefuture.setclosed (); if (!promise.tryfailure (t)) {Logger.warn ("tried to fail the registration p Romise, but it's complete already.                "+" swallowing the cause of the registration failure: ", t); }            }        }

Private Channelfuture dobind (final socketaddress localaddress) {
Final Channelfuture regfuture = Initandregister ();
Final Channel channel = Regfuture.channel ();
if (regfuture.cause () = null) {
return regfuture;
}

Final channelpromise promise;
if (Regfuture.isdone ()) {
Promise = Channel.newpromise ();
DoBind0 (Regfuture, channel, localaddress, Promise);
} else {
Registration almost always fulfilled already and just in case it's not.
Promise = new Defaultchannelpromise (channel, globaleventexecutor.instance);
Regfuture.addlistener (New Channelfuturelistener () {
@Override
public void Operationcomplete (channelfuture) throws Exception {
DoBind0 (Regfuture, channel, localaddress, Promise);
}
});

}

return promise;
}




Netty5 Source Analysis (vii)--Asynchronous execution of future and promise

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.