Future 和 ChannelFuture

一、Future

Netty的Future接口继承了JDK的Future接口,同时提供了更多的方法:

public interface Future<V> extends java.util.concurrent.Future<V> {
    boolean isSuccess();
    Throwable cause();
    Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
    Future<V> removeListener(GenericFutureListener<? extends Future<? super V>> listener);
    Future<V> sync() throws InterruptedException;
    Future<V> await() throws InterruptedException;
    V getNow();
}

任务成功完成后isSuccess()返回true
任务执行过程中有异常,cause()会返回异常对象
任务被取消执行,父接口方法isCancelled返回true
以上3种情况isDone()均为true:

//任务完成
 if (task.isDone()) {
    if (task.isSuccess()) {
        // 成功
    } else if (task.isCancelled()) {
        // 被取消
    } else {
        // 异常
        System.out.print(task.cause())
    }
 }

wait和sync都会阻塞,并等待任务完成
getNow()不会阻塞,会立即返回,但任务尚未执行完成时,会返回null
addListener方法在当前Future对象中添加监听器,当任务完成时,会通知所有的监听器。

二、ChannelFuture

ChannelFuture继承了Netty的Future接口,代表 Netty channel的I/O操作的执行结果。在Netty中所有的I/O操作都是异步的,会立即返回一个代表I/O操作的结果,即ChannelFuture。

在获得执行结果时,推荐使用添加监听器,监听执行完成事件operaionCompleted,而不要使用await方法。在ChannelHandler中调用await,会造成死锁。因为ChannelHandler中的方法通常是I/O线程调用的,再调用await会造成I/O阻塞。

 //错误
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) {
   ChannelFuture future = ctx.channel().close();
   future.awaitUninterruptibly();
   // Perform post-closure operation
   // ...
 }

 // 正确
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) {
   ChannelFuture future = ctx.channel().close();
   future.addListener(new ChannelFutureListener() {
       public void operationComplete(ChannelFuture future) {
           // Perform post-closure operation
           // ...
       }
   });
 }

即使是通过添加ChannelFutureListener的方式获取执行结果,但要注意的是:回调方法operationComplete也是由I/O线程调用的,所以也不能在其中执行耗时任务。如必须,则启用线程池执行。

ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ServerInitializer())
                .bind(8899)
                .sync();

bind方法是异步的,其返回值是ChannelFuture类型。需要调用sync()同步方法,等待绑定动作执行完成。

posted @ 2020-01-19 14:48  codedot  阅读(1313)  评论(0编辑  收藏  举报