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> ;>) 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