netty是event-driven模型,channel的I/O操作都是异步执行,在构建项目的时候,我们不可避免的需要channel的I/O操作具有sequential logic。如在发送数据之后,希望在成功的时候记录一下,失败记录到数据库。或者在聊天的项目中用于防止重复登录场景,发现同一个id建立两次连接,需要先进行对先前的id资源回收,再让后一个id进行登录。这个需要就需要用到ChannelFuture。
ChannelFutrue的UML类图:
/** * 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的通知。
ChannelFuture对象状态只有uncompleted和completed。当一个I/O操作开始时,一个ChannelFuture实例被创建(我知道的暂时除close方法),刚开始时,future对象的实例即不是succeeded,failed,cancelled。因为真正的I/O操作还没有完成。如果正的I/O操作已经完成,那么future的状态将是completed,无论结果是succeeded,failed,cancelled。
各种方法都提供了让你检查I / O操作已经完成,等待完成,和检索结果的I / O操作,它还允许你添加ChannelFutureListeners,当I / O操作完成你可以异步收到通知。
推荐使用addListener(ChannelFutureListener)异步得到通知当一个I / O操作完成后,做任何后续任务,而不是通过调用await方法(降低吞吐量)。但如果你想要业务场景是必须先执行A,然后同步执行B(异步通知不合适的场景),使用await是比较方便的。但await有一个限制,调用await方法的线程不能是I/O 线程(work线程),否则会抛出一个异常,避免死锁。