Netty Source analysis of-future, Channelfuture and Channelpromise detailed (3)

Source: Internet
Author: User
Tags closure throwable

There is already an implementation of the future on the JDK base, which is used to perform asynchronous operations and provides a corresponding method of manipulating the results. However, it also implements its own future within the Netty and inherits the future interface from the JDK, providing additional methods for handling the future in the JDK for asynchronous I/O operations related to Netty

The interface represents the result of an asynchronous computation and provides several methods to monitor whether the calculation is complete, wait for the calculation to complete, and obtain the results of the calculation. Here are examples of how to use it:

{
  interface Archivesearcher {string search (string target);}
  Class App {
    Executorservice executor = ...
    Archivesearcher searcher = ...
    void Showsearch (final String target)
        throws interruptedexception {
      future<string> Future
        = Executor.submit (New callable<string> () {public
          String call () {return
              searcher.search (target);
          }});
      displayotherthings ();//do, things while searching
      try {
        displayText (Future.get ());//Use future< c15/>} catch (Executionexception ex) {cleanup (); return;}}}
  

Future gets to get the result of an asynchronous computation that blocks until the calculation is complete

The above submit method can also be replaced by the following:

{
  futuretask<string> future =
    new futuretask<string> (new callable<string> () {
      public String call () {return
        searcher.search (target);
    }});
  Executor.execute (future);}
the future in the Netty
Public interface Future<v> extends java.util.concurrent.future<v>

The following are the definitions of some of the more important methods, where the AddListener method is very important: the cause method indicates that if I/O operation fails, the Boolean parameter of the Cancel method that returns the exception information indicates whether to interrupt the operation that has already been performed issuccess method represents I Whether the/O operation has been successfully completed. For the future stated in the JDK, the Isdone method can only know if I/O is over, possibly successfully completed, canceled, and abnormally interrupted. This issuccess method of future in Netty can well determine whether the operation is actually successfully completing the sync method blocking until future completes the operation, and if the operation fails, the exception AddListener method is added to the specific listener to future. These listeners are notified immediately when the future Isdone returns TRUE. This is an important extension method in Netty, where the observer pattern is used

The AddListener method incoming listener implements the following interface, that is, the Operationcomplete method is invoked when notified:

Public interface Genericfuturelistener<f extends future<?>> extends EventListener {

    /**
     * invoked When the operation associated with the {@link Future} has been completed.
     *
     * @param future the  source {@link Future} which called this callback
    /void Operationcomplete (F future ) throws Exception;
}

Why is there a Get method in future to obtain an asynchronous result, which extends the listener this way. If we use GET, we will consider exactly when to use it, because it blocks subsequent logical code, and if we use the listener, there is no doubt that it will be more elegant to handle our logical code at a reasonable time channelfuture

Channelfuture inheritance in Netty to Netty's own future

Public interface Channelfuture extends future<void>

Channelfuture represents the result of asynchronous I/O operations in channel, all I/O operations in Netty are asynchronous, and I/O calls are returned directly and can be channelfuture to obtain the result state of the I/O operation. The representation for multiple states is as follows:

                                       +---------------------------+
 *                                      |
 Completed successfully | * +---------------------------+ * +----> IsD
 One () = True |    * +--------------------------+    |   |
 Issuccess () = True |        * |    uncompleted |    |    +===========================+
 * +--------------------------+    | |
 Completed with Failure |      * |    Isdone () = False |    |   +---------------------------+
 * |
 Issuccess () = False |----+----> isdone () = True | * |    IsCancelled () = False |    |       |
 Cause () = Non-null |       * |    Cause () = NULL |    |    +===========================+
 * +--------------------------+    | |
 Completed by cancellation |    *                                 |
 +---------------------------+ * +----> isdone () = True |          *                            |
 IsCancelled () = True | *                                      +---------------------------+

It should be noted that both failure and cancellation indicate that the operation is complete, but the corresponding states are different. Similar to future, you can notify calls when I/O operations are complete by adding channelfuturelistener listeners. This approach is more recommended than the wait () method to get the result status or perform subsequent operations.
In addition, calling await () in Channelhandler is not recommended because the event-driven method in Channelhandler is called by an I/O thread and may never be completed, then await () may also be called by the I/O thread, and will always block, Therefore, a deadlock is generated. For example:

Never do that.
 *//Bad-never do this
 * public void Channelread ({@link channelhandlercontext} ctx, Object msg) {
 *     {@link channelfuture} future = Ctx.channel (). Close ();
 *     future.awaituninterruptibly ();
 *///     Perform post-closure operation *//     ...
 */

 /And should do this:
 *//good
 * public void Channelread ({@link channelhandlercontext} ctx, Object msg) {
 *< c15/>{@link channelfuture} future = Ctx.channel (). Close ();
 *     Future.addlistener (new {@link Channelfuturelistener} () {
 * public         void Operationcomplete ({@link Channelfuture} future) {
 */             /Perform post-closure operation
 *             //...
 *         }
 *     });
 * }

The difference between I/O timeout and await () timeout:

 Never do that *//bad-never do this * {@link Bootstrap} b = ...;
 * {@link channelfuture} f = B.connect (...);
 * f.awaituninterruptibly (Timeunit.seconds); * IF (f.iscancelled ()) {*//Connection attempt cancelled by user *} else if (!f.issuccess ()) {*//You Migh
 t get a nullpointerexception this because the future *//might not be completed yet.
 * F.cause (). Printstacktrace (); *} else {*//Connection established successfully *}//When awaituninterruptibly is the await timeout, channelfuture corresponding connection is probably not complete
 , then performing subsequent operations will be abnormal//and should do so *//good * {@link Bootstrap} b = ...;
 *//Configure the Connect timeout option. * <b>b.option ({@link channeloption}.
 Connect_timeout_millis, 10000);</b> * {@link channelfuture} f = B.connect (...);
 * f.awaituninterruptibly ();
 * *//Now we are sure the future is completed.
 * Assert F.isdone (); * * IF (f.iscancelled ()) {*//Connection attempt cancelled by user *} else if (!f.issuccess ()) {* F.cause (). Printstacktrace (); *} else {*//Connection established successfully *}//When the timeout is added by option, if the timeout is returned as a failure result, and then calls Awaituninter Ruptibly must have been future the operation was completed

Channelfuture to note is the addition of the channel method to obtain the channel:

    /**
     * Returns A channel where the I/O operation associated with this
     * future takes place.
     * *
    Channel Channel ();

The future provided by the JDK can only be manually checked for execution results, and the operation is blocked, Netty is enhanced for channelfuture, and the execution result is obtained by Channelfuturelistener as a callback, Remove to manually check for blocked operations. Note that the Channelfuturelistener Operationcomplete method is performed by an I/O thread, so be careful not to perform time-consuming operations here, or else you will need to perform the Channelpromise

Channelpromise is a special channelfuture that can be written.

Public interface Channelpromise extends Channelfuture, promise<void>

For promise:

Public interface Promise<v> extends future<v>

Defines a method that identifies future success or failure, and each future can only be identified once, and if successful, it will be notified before the defined listeners

    /** * Marks This future as a success and notifies all * listeners.
     * IF It is success or failed already it'll throw an {@link illegalstateexception}.

    * * promise<v> setsuccess (V result);
     /** * Marks This future as a success and notifies all * listeners. * * @return {@code true} if and only if successfully marked this future as * a success.
     Otherwise {@code false} because this future is * already marked as either a success or a failure.

    * * Boolean trysuccess (V result);
     /** * Marks This future as a failure and notifies all * listeners.
     * IF It is success or failed already it'll throw an {@link illegalstateexception}.

    * * promise<v> setfailure (throwable cause);
     /** * Marks This future as a failure and notifies all * listeners. * * @return {@code true} if and only if successfully marked this future as * a failUre.
     Otherwise {@code false} because this future is * already marked as either a success or a failure.

    * * Boolean tryfailure (Throwable cause);
     /** * Make this future impossible to cancel.          * * @return {@code true} if and only if successfully marked this future as uncancellable or it are already done *  Without being cancelled.
     {@code false} If this future has been cancelled already. * * Boolean setuncancellable ();

In the Defaultchannelpromise default implementation, the corresponding listeners is notified when the expression is successful

@Override public
    channelpromise setsuccess (Void result) {
        super.setsuccess (result);
        return this;
    }

In the Setsuccess method:

private void Notifylistenersnow () {... for (;;)  {if (listeners instanceof defaultfuturelisteners) {NotifyListeners0 (defaultfuturelisteners)
            listeners);
            else {NotifyListener0 (this, (genericfuturelistener<?>) listeners);  } synchronized (this) {if (this.listeners = = null) {//nothing can throw From within this method, so setting notifyinglisteners back to False does not//need to be in a FINA
                    Lly block.
                    Notifyinglisteners = false;
                Return
                } listeners = This.listeners;
            This.listeners = null; }
        }
    }

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.