一、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()同步方法,等待绑定动作执行完成。