ChannelFuture
异步Channel IO操作的结果占位符
Netty中所有的IO都是异步的,这意味着任何IO调用都将立即返回,并且不保证在调用结束时所请求的IO操作已完成
ChannelFuture包含了未完成或已完成。
当IO操作开始时,将创建一个新的Future对象,新的Future最初是未完成的 - 它既没有成功,也没有被取消,也没有被取消,因为IO操作还没有完成。
如果IO操作成功完成,失败或取消,则将使用更具体的信息(例如失败原因)将Future标记为已完成。
请注意,即使失败和取消也属于已完成的状态。
很多方法用来检查IO操作是否已完成,等待完成,并检索IO操作的结果。
它还允许您添加ChannelFutureListeners,以便在IO操作完成时收到通知。
addListener(GenericFutureListener)优于await();
addListener非阻塞,只需要添加到Future,最佳性能和资源利用率
await是阻塞的,调用后线程一直阻塞到操作完成,实现顺序逻辑容易
Tips:
不要在ChannelHandler中调用await()
ChannelHandler中的事件处理程序方法通常由IO线程调用。
如果事件处理程序方法(由IO线程调用)调用await(),则它正在等待的IO操作可能永远不会完成,因为await()可以阻止它正在等待的IO操作,这是一个死锁。
// BAD - NEVER DO THIS
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ChannelFuture future = ctx.channel().close();
future.awaitUninterruptibly();
// Perform post-closure operation
// ...
}
// GOOD
@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
// ...
}
});
}
不要混淆IO超时和等待超时
使用await(long),await(long,TimeUnit),awaitUninterruptibly(long)或awaitUninterruptibly(long,TimeUnit)指定的超时值与IO超时完全无关。
如果IO操作超时,则将来标记为“已完成但失败”,如上图所示。 例如,应通过特定于传输的选项配置连接超时:
// BAD - NEVER DO THIS
Bootstrap b = ...;
ChannelFuture f = b.connect(...);
f.awaitUninterruptibly(10, TimeUnit.SECONDS);
if (f.isCancelled()) {
// Connection attempt cancelled by user
} else if (!f.isSuccess()) {
// You might get a NullPointerException here because the future
// might not be completed yet.
f.cause().printStackTrace();
} else {
// Connection established successfully
}
// GOOD
Bootstrap b = ...;
// Configure the connect timeout option.
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
ChannelFuture f = b.connect(...);
f.awaitUninterruptibly();
// Now we are sure the future is completed.
assert f.isDone();
if (f.isCancelled()) {
// Connection attempt cancelled by user
} else if (!f.isSuccess()) {
f.cause().printStackTrace();
} else {
// Connection established successfully
}