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