Interface Future<V>

  • All Known Subinterfaces:
    ChannelGroupFuture, RunnableFuture<V>, RunnableScheduledFuture<V>
    All Known Implementing Classes:
    DefaultPromise

    public interface Future<V>
    The result of an asynchronous operation.

    An asynchronous operation is one that might be completed outside a given thread of execution. The operation can either be performing computation, or I/O, or both.

    All I/O operations in Netty are asynchronous. It means any I/O calls will return immediately with no guarantee that the requested I/O operation has been completed at the end of the call. Instead, you will be returned with a Future instance which gives you the information about the result or status of the I/O operation.

    A Future is either uncompleted or completed. When an I/O operation begins, a new future object is created. The new future is uncompleted initially - it is neither succeeded, failed, nor cancelled because the I/O operation is not finished yet. If the I/O operation is finished either successfully, with failure, or by cancellation, the future is marked as completed with more specific information, such as the cause of the failure. Please note that even failure and cancellation belong to the completed state.

                                          +---------------------------+
                                          | Completed successfully    |
                                          +---------------------------+
                                     +---->      isDone() = true      |
     +--------------------------+    |    |   isSuccess() = true      |
     |        Uncompleted       |    |    +===========================+
     +--------------------------+    |    | Completed with failure    |
     |      isDone() = false    |    |    +---------------------------+
     |   isSuccess() = false    |----+---->      isDone() = true      |
     | isCancelled() = false    |    |    |       cause() = non-null  |
     |       cause() = throws   |    |    +===========================+
     |      getNow() = throws   |    |    | Completed by cancellation |
     +--------------------------+    |    +---------------------------+
                                     +---->      isDone() = true      |
                                          | isCancelled() = true      |
                                          +---------------------------+
     

    Various methods are provided to let you check if the I/O operation has been completed, wait for the completion, and retrieve the result of the I/O operation. It also allows you to add FutureListeners so you can get notified when the I/O operation is completed.

    Prefer addListener(FutureListener) to FutureCompletionStage.await()

    It is recommended to prefer addListener(FutureListener), or addListener(Object, FutureContextListener), to FutureCompletionStage.await() wherever possible to get notified when an I/O operation is done and to do any follow-up tasks.

    The addListener(FutureListener) method is non-blocking. It simply adds the specified FutureListener to the Future, and the I/O thread will notify the listeners when the I/O operation associated with the future is done. The FutureListener and FutureContextListener callbacks yield the best performance and resource utilization because it does not block at all, but it could be tricky to implement a sequential logic if you are not used to event-driven programming.

    By contrast, FutureCompletionStage.await() is a blocking operation. Once called, the caller thread blocks until the operation is done. It is easier to implement a sequential logic with FutureCompletionStage.await(), but the caller thread blocks unnecessarily until the I/O operation is done and there's relatively expensive cost of inter-thread notification. Moreover, there's a chance of deadlock in a particular circumstance, which is described below.

    Do not call FutureCompletionStage.await() inside a ChannelHandler

    The event handler methods in ChannelHandler are usually called by an I/O thread. If FutureCompletionStage.await() is called by an event handler method, which is called by the I/O thread, the I/O operation it is waiting for might never complete because FutureCompletionStage.await() can block the I/O operation it is waiting for, which is a deadlock.

     // BAD - NEVER DO THIS
     @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) {
         Future future = ctx.channel().close();
         future.asStage().await();
         // Perform post-closure operation
         // ...
     }
    
     // GOOD
     @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) {
         Future future = ctx.channel().close();
         future.addListener(new FutureListener() {
             public void operationComplete(Future future) {
                 // Perform post-closure operation
                 // ...
             }
         });
     }
     

    In spite of the disadvantages mentioned above, there are certainly the cases where it is more convenient to call FutureCompletionStage.await(). In such a case, please make sure you do not call FutureCompletionStage.await() in an I/O thread. Otherwise, BlockingOperationException will be raised to prevent a deadlock.

    Do not confuse I/O timeout and await timeout

    The timeout value you specify with FutureCompletionStage.await(long, TimeUnit) is not related to the I/O timeout at all. If an I/O operation times out, the future will be marked as 'completed with failure,' as depicted in the diagram above. For example, connect timeout should be configured via a transport-specific option:

     // BAD - NEVER DO THIS
     Bootstrap b = ...;
     Future f = b.connect(...);
     f.asStage().await(10, TimeUnit.SECONDS);
     if (f.isCancelled()) {
         // Connection attempt cancelled by user
     } else if (!f.isSuccess()) {
         // You might get a NullPointerException here because the future
         // might not be completed yet.
         f.cause().printStackTrace();
     } else {
         // Connection established successfully
     }
    
     // GOOD
     Bootstrap b = ...;
     // Configure the connect timeout option.
     b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
     Future f = b.connect(...);
     f.asStage().await();
    
     // 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
     }
     
    • Method Detail

      • addListener

        Future<V> addListener​(FutureListener<? super V> listener)
        Adds the specified listener to this future. The specified listener is notified when this future is done. If this future is already completed, the specified listener is notified immediately.
        Parameters:
        listener - The listener to be called when this future completes. The listener will be passed this future as an argument.
        Returns:
        this future object.
      • addListener

        <C> Future<V> addListener​(C context,
                                  FutureContextListener<? super C,​? super V> listener)
        Adds the specified listener to this future. The specified listener is notified when this future is done. If this future is already completed, the specified listener is notified immediately.
        Parameters:
        context - The context object that will be passed to the listener when this future completes.
        listener - The listener to be called when this future completes. The listener will be passed the given context, and this future.
        Returns:
        this future object.
      • map

        default <R> Future<R> map​(Function<V,​R> mapper)
        Creates a new Future that will complete with the result of this Future mapped through the given mapper function.

        If this future fails, then the returned future will fail as well, with the same exception. Cancellation of either future will cancel the other. If the mapper function throws, the returned future will fail, but this future will be unaffected.

        Type Parameters:
        R - The result type of the mapper function, and of the returned future.
        Parameters:
        mapper - The function that will convert the result of this future into the result of the returned future.
        Returns:
        A new future instance that will complete with the mapped result of this future.
      • flatMap

        default <R> Future<R> flatMap​(Function<V,​Future<R>> mapper)
        Creates a new Future that will complete with the result of this Future flat-mapped through the given mapper function.

        The "flat" in "flat-map" means the given mapper function produces a result that itself is a future-of-R, yet this method also returns a future-of-R, rather than a future-of-future-of-R. In other words, if the same mapper function was used with the map(Function) method, you would get back a Future<Future<R>>. These nested futures are "flattened" into a Future<R> by this method.

        Effectively, this method behaves similar to this serial code, except asynchronously and with proper exception and cancellation handling:

        
         V x = future.sync().getNow();
         Future<R> y = mapper.apply(x);
         R result = y.sync().getNow();
         

        If the given future fails, then the returned future will fail as well, with the same exception. Cancellation of either future will cancel the other. If the mapper function throws, the returned future will fail, but this future will be unaffected.

        Type Parameters:
        R - The result type of the mapper function, and of the returned future.
        Parameters:
        mapper - The function that will convert the result of this future into the result of the returned future.
        Returns:
        A new future instance that will complete with the mapped result of this future.
      • cascadeTo

        default Future<V> cascadeTo​(Promise<? super V> promise)
        Link the Future and Promise such that if the Future completes the Promise will be notified. Cancellation is propagated both ways such that if the Future is cancelled the Promise is cancelled and vice-versa.
        Parameters:
        promise - the Promise which will be notified
        Returns:
        itself
      • cancel

        boolean cancel()
        Cancel this asynchronous operation, unless it has already been completed or is not cancellable.

        A cancelled operation is considered to be done and failed.

        If the cancellation was successful, the result of this operation will be that it has failed with a CancellationException.

        Cancellation will not cause any threads working on the operation to be interrupted.

        Returns:
        true if the operation was cancelled by this call, otherwise false.
      • isSuccess

        boolean isSuccess()
        Returns true if and only if the operation was completed successfully.
      • isFailed

        boolean isFailed()
        Returns true if and only if the operation was completed and failed.
      • isCancelled

        boolean isCancelled()
        Return true if this operation has been cancelled.
        Returns:
        true if this operation has been cancelled, otherwise false.
      • isDone

        boolean isDone()
        Return true if this operation has been completed either successfully, unsuccessfully, or through cancellation.
        Returns:
        true if this operation has completed, otherwise false.
      • isCancellable

        boolean isCancellable()
        Returns true if and only if the operation can be cancelled via cancel(). Note that this is inherently racy, as the operation could be made uncancellable at any time.
        Returns:
        true if this operation can be cancelled.
      • getNow

        V getNow()
        Return the successful result of this asynchronous operation, if any. If the operation has not yet been completed, then this will throw IllegalStateException. If the operation has been cancelled or failed with an exception, then this returns null. Note that asynchronous operations can also be completed successfully with a null result.
        Returns:
        the result of this operation, if completed successfully.
        Throws:
        IllegalStateException - if this Future or Promise has not completed yet.
      • cause

        Throwable cause()
        Returns the cause of the failed operation if the operation has failed.
        Returns:
        The cause of the failure, if any. Otherwise null if succeeded.
        Throws:
        IllegalStateException - if this Promise has not completed yet.