一、JDK的Future
从这个类的注释中,我们可以了解到:
Future 类就是代表了异步计算的结果,这个接口的主要方法就是检查计算是否已完成,等待计算,然后返回计算结果。
当计算完成后,结果只能通过get方法返回;如果有必要会堵塞直到它计算完成。
可以通过cancel方法取消。增加的方法来判断任务是否正常完成或者被取消。一旦计算已经完成,计算不能被取消。
如果你想要使用Future 来取消,但是不提供一个可用的结果,你可以声明Futrue 的类型,但会返回null 作为一个基本任务的结果。
FutureTask 类是Futrue类的一个实现类,实现了Runnable接口,可以被Executor 执行。
二、JDK的FutureTask
- 一个可取消的异步计算,这个类提供了对Future 的基本实现。有对计算的启动和取消方法,查询计算是否已完成,以及返回计算的结果。
- 计算的结果只有在计算已完成后才能返回,如果计算没有完成,get方法会堵塞。一旦计算已经完成,计算不能被重启或取消。(除非计算是被runAndReset方法调用)
- 可以看到这个类中有表示计算执行的状态
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
- 在判断当前计算是否已完成等状态时,都是通过这个字段来进行判断。
三、Netty的Future
1、说明
Netty的【Future】扩展了【java.util.concurrent.Future】:
- 保留jdk Future的若干阻塞行为的接口
- 同时增加了【listener类型的接口】,通过监听器可以让异步执行更加有效率(当异步执行有结果时进行回调)
2、Netty的Future继承体系与方法如下
四、Netty的io.netty.channel.ChannelFuture
netty的【ChannelFuture】又扩展了netty的【Future】
- 提供和一个Channel进行绑定(通过ChannelFuture的channel方法可以获取对应的Channel对象)。
- ChannelFuture的大部分接口都是Override的io.netty.channel.ChannelFuture
- ①将类型具化成ChannelFuture
- ②将参数GenericFutureListener的范型具化成 <? extends Future<? super Void>>,其中<? super Void>表示了一种没有返回值的异步调用:
4.1 ChannelFuture的状态
ChannelFuture有两种状态:未完成(uncompleted)和完成(completed).
当令Channel开始一个I/O操作时,会创建一个新的ChannelFuture去异步完成操作.
被创建时的ChannelFuture处于uncompleted状态(非失败,非成功,非取消);一旦ChannelFuture完成I/O操作,ChannelFuture将处于completed状态,结果可能有三种:
- 操作成功
- 操作失败
- 操作被取消(I/O操作被主动终止)
需要关注ChannelFuture的其它属性来获取异常信息。
下图是 Netty API 中提供的ChannelFuture状态迁移图:
+---------------------------+
| Completed successfully |
+---------------------------+
+----> isDone() = true |
+--------------------------+ | | isSuccess() = true |
| Uncompleted | | +===========================+
+--------------------------+ | | Completed with failure |
| isDone() = false | | +---------------------------+
| isSuccess() = false |----+----> isDone() = true |
| isCancelled() = false | | | cause() = non-null |
| cause() = null | | +===========================+
+--------------------------+ | | Completed by cancellation |
| +---------------------------+
+----> isDone() = true |
| isCancelled() = true |
+---------------------------+
4.2 ChannelFutureListener监听接口
ChannelFuture的get()方法获取异步操作的结果,但是切记一定要设置超时时间。
Netty建议通过ChannelFutureListener接口执行异步操作结束后的回调
示例代码:
@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
// ...
}
});
}
另外,ChannelFuture允许添加一个或多个(移除一个或多个)ChannelFutureListener监听接口,方法名:addListener(), addListeners(), removeListener(), removeListeners()
五、Netty的Promise
从Promise接口的方法上可以看出,其实Promise就是一个可写的Future,没有我想象的那么复杂.其实如果是理解了Future,那么Promise其实也是能够理解了.从它继承Future和添加的几个借口方法也能看出来它的大致用途。
1、说明
netty的【Promise】也扩展了netty的【Future】
- 表示一种可写的Future:可以自定义设置异步执行的结果
六、Netty的ChannelPromise
1、说明
netty的【ChannelPromise】也扩展了【Promise】、【ChannelFuture】
- 绑定了Channel
- 可以写异步执行结果
- 具备【listener】功能
大部分方法都是Override父接口的方法:
- 返回值声明成了具化的ChannelPromise类型
- 参数GenericFutureListener的范型声明成了具化的:<? extends Future<? super Void>>
2、实现
DefaultChannelPromise是ChannelPromise的实现类,是实际运行时的Promise实例。
- 继承体系中,DefaultChannelPromise与DefaultPromise分别负责对ChannelPromise的接口以及Promise的接口进行实现:
- 比如:DefaultPromise中的对addListener方法的实现:
@Override
public Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) {
checkNotNull(listener, "listener");
synchronized (this) {
addListener0(listener);
}
if (isDone()) {
notifyListeners();
}
return this;
}
private void addListener0(GenericFutureListener<? extends Future<? super V>> listener) {
if (listeners == null) {
listeners = listener;
} else if (listeners instanceof DefaultFutureListeners) {
((DefaultFutureListeners) listeners).add(listener);
} else {
listeners = new DefaultFutureListeners((GenericFutureListener<?>) listeners, listener);
}
}
private void notifyListeners() {
EventExecutor executor = executor();
if (executor.inEventLoop()) {
final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
final int stackDepth = threadLocals.futureListenerStackDepth();
if (stackDepth < MAX_LISTENER_STACK_DEPTH) {
threadLocals.setFutureListenerStackDepth(stackDepth + 1);
try {
notifyListenersNow();
} finally {
threadLocals.setFutureListenerStackDepth(stackDepth);
}
return;
}
}
safeExecute(executor, new Runnable() {
@Override
public void run() {
notifyListenersNow();
}
});
}
- 可见,addListener方法中会先判断异步任务执行的状态isDone,如果异步任务执行完成就立即通知监听者,否则,加入监听者队列
- 通知监听者就是找一个线程来执行调用监听者的回调函数