在应用中以任务的方式实现功能时,需要考虑到任务间的依赖关系。当任务强依赖上一个任务的结果时,任务间的消息通知就需要重视起来。任务间的消息通知分为同步和异步方式,同步就是消息的发送方要等待消息返回才能继续处理其他事情,而异步就是不需要等待消息返回而是通过条件变量、信号量、回调等方式实现消息通知。
JDK提供了 「Future
」 来表示一个任务的执行结果。实现一个任务时需要实现 Runnable
或 Callable
结果,Future
可以检测任务是否完成,获取任务的执行结果,取消任务等。Future
是一个任务的句柄,从Future
可以获取任务的状态和执行结果,即使这个结果可能立即可用或者未来某个时间可用。「Promise
」 是一个可以写入结果或异常的对象,只能写入一次。Promise
表示 Future
的执行结果,成功或者异常。每个 Promise
关联一个 Future
,对 Promise
进行写入会使 Future
的值可用。
Future和Promise来源于函数式语言,其目的是分离一个值和产生值的方法,从而简化异步代码的处理。
Netty中的Future
因为JDK的 Future
支持的功能比较简陋,Netty提供了 Future
的实现,扩展了 Future
的功能。
Netty中关于 Future
框架的实现位于 common
模块中,至于在 transport
中的扩展如 ChannelFuture
这里没有涉及,那部分内容只是 Future
的应用。
从IDEA生成的类图来看Netty的关于 Future
的扩展有三类:
Future -> AbstractFuture -> CompleteFuture -> FailedFuture,SucceededFuture
。针对只需要关注任务的最终执行结果,中间不需要对任务执行成功或异常设置回调。AbstractFuture
提供了get()
操作的实现,CompleteFuture
代表一个执行完毕的任务结果或异常。
Netty的
Future
实现增加了添加和移除回调的方法,从而实现异步编程,回调或者说事件通知的实现是基于观察者模式。Future
也支持同步获取结果,但是JDK的Future
的get()
操作从语义上来说是一个获取结果的方法,如果不是阅读文档完全获取不到这个方法会阻塞线程直到能够成功获取结果或抛出异常。Netty提供了await()
和sync()
方法阻塞当前线程直到结果完成,从语义上来说await()
用作需要等待任务完成,但是不需要获取任务执行结果或无结果,sync()
用作需要同步阻塞且需要获取结果的场景,当sync()
执行结束后调用get()
获取执行结果。Netty的
Promise
实现是通过继承Future
实现的,在Promise
中提供了设置任务执行结果的方法。在DefaultPromise
中提供了实现,关于回调的实现是一个观察者模式的实现。在Netty的监听器接口的顶层接口是JDK的EventListener
接口,这是JDK的事件通知接口,相关的还有事件对象的类定义EventObject
。值得注意的是回调地狱的问题,Netty默认回调的嵌套上限是8层。JDK8提供的CompletableFuture
支持对Future
进行计算,而不是Future
的结果从而解决了开发中需要用到的多重回调问题。Netty还提供了
ProgressiveFuture
和ProgressivePromise
抽象,这是为了解决任务处理不同的阶段需要进行不同的处理的问题,如下载任务,需要不断反馈下载进度,又或者如支持依赖的调度任务进行到不同阶段需要触发不同的任务执行。ProgressivePromise
主要增加了setProgress()
和tryProgress()
方法。