netty框架中的ChannelFuture 详解

来源:互联网 发布:北大青鸟软件测试 编辑:程序博客网 时间:2024/06/08 01:00

netty是event-driven模型,channel的I/O操作都是异步执行,在构建项目的时候,我们不可避免的需要channel的I/O操作具有sequential logic。如在发送数据之后,希望在成功的时候记录一下,失败记录到数据库。或者在聊天的项目中用于防止重复登录场景,发现同一个id建立两次连接,需要先进行对先前的id资源回收,再让后一个id进行登录。这个需要就需要用到ChannelFuture。

ChannelFutrue的UML类图:

netty ChannelFuture - zhanghua.1199 - 郁,加没

ChannelFuture可以增加ChannelFutureListener对象(可以增加多个,当操作完成,会顺序调用listener的operationComplete方法),
netty ChannelFuture - zhanghua.1199 - 郁,加没

 里面的CLOSE和CLOSE_ON_FAILURE实现好的两个listener内部类,里面的代码是:

 /**     * A {@link ChannelFutureListener} that closes the {@link Channel} which is     * associated with the specified {@link ChannelFuture}.     */    ChannelFutureListener CLOSE = new ChannelFutureListener() {        public void operationComplete(ChannelFuture future) {            future.getChannel().close();        }    };

    /**     * A {@link ChannelFutureListener} that closes the {@link Channel} when the     * operation ended up with a failure or cancellation rather than a success.     */    ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() {        public void operationComplete(ChannelFuture future) {            if (!future.isSuccess()) {                future.getChannel().close();            }        }    };


这里说明一点:Channel的close方法返回的ChannelFuture永远都是同一个future实例,所以你可以在channel一打开的情况下,就注册一些关闭的流程。执行channel.close()方法有两个地方会收到通知,一个是handler,一个是future。handler会在future之前收到channel close的通知
官方的详细介绍:
     在netty中所有的I/O操作都是异步,这意味着netty提供的I/O方法调用都将立即返回,会返回一个ChannelFuture对象的实像,它将会给你一些信息,关于I/O执行状态的结果,但此时不能保证真正的I/O操作已经完成。

    ChannelFuture对象状态只有uncompleted和completed。当一个I/O操作开始时,一个ChannelFuture实例被创建(我知道的暂时除close方法),刚开始时,future对象的实例即不是succeeded,failed,cancelled。因为真正的I/O操作还没有完成。如果正的I/O操作已经完成,那么future的状态将是completed,无论结果是succeeded,failed,cancelled。

netty ChannelFuture - zhanghua.1199 - 郁,加没

各种方法都提供了让你检查I / O操作已经完成,等待完成,和检索结果的I / O操作,它还允许你添加ChannelFutureListeners,当I / O操作完成你可以异步收到通知。

推荐使用addListener(ChannelFutureListener)异步得到通知当一个I / O操作完成后,做任何后续任务,而不是通过调用await方法(降低吞吐量)。但如果你想要业务场景是必须先执行A,然后同步执行B(异步通知不合适的场景),使用await是比较方便的。但await有一个限制,调用await方法的线程不能是I/O 线程(work线程),否则会抛出一个异常,避免死锁。


0 0