org.jboss.netty.channel
接口 ChannelFuture

所有已知实现类:
CompleteChannelFuture, DefaultChannelFuture, FailedChannelFuture, SucceededChannelFuture

public interface ChannelFuture

一个通道的异步 I/O操作结果.

在Netty里所有I/O操作都是异步的. 这意味着任何I/O操作都不会保证I/O请求在调用后完成,而是会立即返回.相反,会返回一个 ChannelFuture实例 以提供该I/O操作的结果或状态信息.

一个ChannelFuture要么未完成要么完成. 当I/O操作开始,一个新的future对象就被创建.一个future初始是未完成的 - 因为I/O操作还没有结束,它既不是成功,失败也不是取消.如果I/O操作已经完成,要么成功或失败,要么取消 ,使用更多的信息标识future为完成,如发生失败 .请注意失败和取消也属于完成状态.

                                      +---------------------------+
                                      |          成功完成                         |
                                      +---------------------------+
                                 +---->      isDone() = true      |
 +--------------------------+    |    |   isSuccess() = true      |
 |          未完成             |    |    +===========================+
 +--------------------------+    |    |          失败完成                         |
 |      isDone() = false    |    |    +---------------------------+
 |   isSuccess() = false    |----+---->   isDone() = true         |
 | isCancelled() = false    |    |    | getCause() = non-null     |
 |    getCause() = null     |    |    +===========================+
 +--------------------------+    |    |          取消完成                         |
                                 |    +---------------------------+
                                 +---->      isDone() = true      |
                                      | isCancelled() = true      |
                                      +---------------------------+
 
有各种各样的方法可以让你检测I/O的已经完成 , 等待完成和取回I/O操作结果. 它也允许你添加 ChannelFutureListener以便当I/O操作完成你可以收到通知.

使用addListener(ChannelFutureListener)await()更好

建议优先使用addListener(ChannelFutureListener),再使用await() ,因为不管在什么地方,当I/O操作完成你都可以收到通知,并执行后续任务.

addListener(ChannelFutureListener)是非阻塞的.它简单的为 ChannelGroupFuture添加特定的ChannelGroupFutureListener ,并且当该future关联的I/O操作完成后I/O线程会通知这些监听器.由于它是不阻塞的,所以ChannelFutureListener 有最好的性能和资源利用率, 但是如果你不是使用事件驱动编程,它实现顺序逻辑就很棘手.

相比之下, await()是阻塞操作.一旦调用,调用线程会阻塞直到所有I/O操作完成为止.虽然使用await() 可以很简单的实现一个顺序逻辑 ,但是调用线程会不必要的阻塞直到所有I/O操作完成和相当昂贵的交互线程通知的开销.而且,在特别情况下还有可能会出现死锁,如下所描述.

别在ChannelHandler里面调用await()

ChannelHandler的事件处理方法会经常被I/O线程调用,除了ChannelPipeline里的 ExecutionHandler.如果await() 被一个I/O线程调用的事件处理方法调用,该I/O操作会是一个永远不会完成一直等待的操作,因为await() 会阻塞该I/O操作,所以是一个死锁.

 // BAD - 别这么做
 @Override
 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
     if (e.getMessage() instanceof GoodByeMessage) {
         ChannelFuture future = e.getChannel().close();
         future.awaitUninterruptibly();
         // Perform post-closure operation
         // ...
     }
 }
 
 // GOOD
 @Override
 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
     if (e.getMessage() instanceof GoodByeMessage) {
         ChannelFuture future = e.getChannel().close();
         future.addListener(new ChannelFutureListener() {
             public void operationComplete(ChannelFuture future) {
                 // Perform post-closure operation
                 // ...
             }
         });
     }
 }
 

尽管有以上提到的缺点,在某些情况下,调用await()会更方便.在这种情况下,请确保你没有在一个I/O线程里调用 await().否则,会抛出IllegalStateException异常以防止死锁.

别混淆I/O超时和await超时

使用await(long), await(long, TimeUnit), awaitUninterruptibly(long), or awaitUninterruptibly(long, TimeUnit) 指定的超时值与I/O超时一点关系都没有.如果一个I/O操作超时,该future会被标识为 '完成失败' 正如上图所描述.例如,连接超时应该通过传输属性来制定:
 // BAD - 别这么做
 ClientBootstrap b = ...;
 ChannelFuture f = b.connect(...);
 f.awaitUninterruptibly(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.getCause().printStackTrace();
 } else {
     // Connection established successfully
 }
 
 // GOOD
 ClientBootstrap b = ...;
 // Configure the connect timeout option.
 b.setOption("connectTimeoutMillis", 10000);
 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.getCause().printStackTrace();
 } else {
     // Connection established successfully
 }
 


方法摘要
 void addListener(ChannelFutureListener listener)
          添加指定的监听器到该future.当该future完成 ,该监听器会收到通知.如果该future已经完成,指定的监听器也会立刻收到通知.
 ChannelFuture await()
          等待该future完成
 boolean await(long timeoutMillis)
          在指定的时间限制内等待future的完成.
 boolean await(long timeout, java.util.concurrent.TimeUnit unit)
          在指定的时间限制内等待future的完成.
 ChannelFuture awaitUninterruptibly()
          等待该future完成.该方法会捕捉InterruptedException并安静丢弃.
 boolean awaitUninterruptibly(long timeoutMillis)
          在指定的时间限制内等待future的完成.该方法会捕捉InterruptedException并丢弃异常.
 boolean awaitUninterruptibly(long timeout, java.util.concurrent.TimeUnit unit)
          在指定的时间限制内等待future的完成.该方法会捕捉InterruptedException并丢弃异常.
 boolean cancel()
          取消该future关联的I/O操作,如果取消成功则通知所有监听器.
 java.lang.Throwable getCause()
          如果I/O操作失败,则返回导致I/O操作失败的原因.
 Channel getChannel()
          返回该future关联发生I/O操作的Channel.
 boolean isCancelled()
          只有该future被使用cancel()方法取消才返回true.
 boolean isDone()
          只有当该future完成了返回true,不管操作是否成功、失败或取消.
 boolean isSuccess()
          只有该future的I/O操作成功完成才返回true.
 void removeListener(ChannelFutureListener listener)
          移除该future里指定的监听器.当该future完成 ,该监听器会收到通知.如果指定的监听器不再关联该future,该方法不做任何事.
 boolean setFailure(java.lang.Throwable cause)
          标识该future为失败并通知所有监听器.
 boolean setProgress(long amount, long current, long total)
          通知实现ChannelFutureProgressListener接口的监听器该操作的进度.
 boolean setSuccess()
          标识该future为成功并通知所有监听器.
 

方法详细信息

getChannel

Channel getChannel()
返回该future关联发生I/O操作的Channel.


isDone

boolean isDone()
只有当该future完成了返回true,不管操作是否成功、失败或取消.


isCancelled

boolean isCancelled()
只有该future被使用cancel()方法取消才返回true.


isSuccess

boolean isSuccess()
只有该future的I/O操作成功完成才返回true.


getCause

java.lang.Throwable getCause()
如果I/O操作失败,则返回导致I/O操作失败的原因.

返回:
失败的原因.如果是成功或还没完成则返回null.

cancel

boolean cancel()
取消该future关联的I/O操作,如果取消成功则通知所有监听器.

返回:
只有操作被取消才返回true.如果操作不被取消或已经完成则返回false.

setSuccess

boolean setSuccess()
标识该future为成功并通知所有监听器.

返回:
只有成功标识了该future为成功才返回true.如果该future已经被标识过成功或失败则返回 false.

setFailure

boolean setFailure(java.lang.Throwable cause)
标识该future为失败并通知所有监听器.

返回:
只有成功标识了该future为失败才返回true.如果该future已经被标识过成功或失败则返回 false.

setProgress

boolean setProgress(long amount,
                    long current,
                    long total)
通知实现ChannelFutureProgressListener接口的监听器该操作的进度. 请注意如果该future已经完成则该方法不会做任何事直接返回false.

返回:
true if and only if notification was made.

addListener

void addListener(ChannelFutureListener listener)
添加指定的监听器到该future.当该future完成 ,该监听器会收到通知.如果该future已经完成,指定的监听器也会立刻收到通知.


removeListener

void removeListener(ChannelFutureListener listener)
移除该future里指定的监听器.当该future完成 ,该监听器会收到通知.如果指定的监听器不再关联该future,该方法不做任何事.


await

ChannelFuture await()
                    throws java.lang.InterruptedException
等待该future完成

抛出:
java.lang.InterruptedException - 如果当前线程被打断则抛出异常

awaitUninterruptibly

ChannelFuture awaitUninterruptibly()
等待该future完成.该方法会捕捉InterruptedException并安静丢弃.


await

boolean await(long timeout,
              java.util.concurrent.TimeUnit unit)
              throws java.lang.InterruptedException
在指定的时间限制内等待future的完成.

返回:
只有在指定时间限制内完成才返回true
抛出:
java.lang.InterruptedException - 如果当前线程被打断则抛出异常

await

boolean await(long timeoutMillis)
              throws java.lang.InterruptedException
在指定的时间限制内等待future的完成.

返回:
只有在指定时间限制内完成才返回true
抛出:
java.lang.InterruptedException - 如果当前线程被打断则抛出异常

awaitUninterruptibly

boolean awaitUninterruptibly(long timeout,
                             java.util.concurrent.TimeUnit unit)
在指定的时间限制内等待future的完成.该方法会捕捉InterruptedException并丢弃异常.

返回:
只有在指定时间限制内完成才返回true

awaitUninterruptibly

boolean awaitUninterruptibly(long timeoutMillis)
在指定的时间限制内等待future的完成.该方法会捕捉InterruptedException并丢弃异常.

返回:
只有在指定时间限制内完成才返回true