netty中的future继承自jdk中cocurrent包下future的接口。编程
Future的V能够是void,不必定是有返回值的,因此经过返回值来判断task isDone()是错误的。因此isDone的判断不该该经过返回值来作。只有isDone了以后,才去作get操做。因此get里面也会抛异常。数组
经过isDone来判断是否结束了。promise
正常的Future在jdk中的使用方法,Future针对的就是一个task,task每每是一个runnable,Future和runnable在一块儿,他就是一个task。异步
FutureTask<String> future=new FutureTask<>(task);函数式编程
executor.execute(future);函数
把future放在execute里面,执行的是runnable对象,只不过是用Future管理了一下。Task里面须要设定状态,Future是针对要执行的任务的封装,对任务作了一个加强的操做。可是netty里面的future,这些方法是不够的。因此添加了一些接口,并且是异步的操做。ui
jdk里面的Future是isDone,没有判断是否成功,只判断了是否取消了(isCalled),netty里面的future是isSuccess,还加了是否能够取消。是对状态判断的补充。cause方法,抛出异常以后能够知道是怎样跑出的什么异常。netty的future,很核心的一个方法:addListener,经过isDone判断这个future结束了,结束了以后立马唤醒这个listener。至关于就是一个回调。netty
有增长通常就有删除,因此有removeListener。对象
future须要特别注意的方法有三个,isDone,isSuccess,addListener。blog
知道这个以后,再来讲一下函数式编程,函数式编程会强调一个promise。就是成功以后会作什么事,失败以后会作什么事。promise和响应式编程很像,有onNext,onComplete,onError这几种处理,你有元素下发的时候怎么处理,当你正常结束的时候怎么处理,当出错的时候怎么处理。咱们的正常使用只是一个地址的访问,给我返回结果,咱们只须要对结果进行判断它是成功仍是失败。若是只须要考虑这2种,使用promise就能够了。因此future又拓展了一个promise。
如何判断是isSuccess,promise提供了setSuccess,trySuccess,标记为success同时通知全部的listener。
promise接口继承自future,因此它重写了一些方法,把返回值有Future改成了Promise。以addListener为例,在函数式编程中,添加的是一个动做,操做的是Future,很明显是一个函数式接口,就是结束以后应该作什么,只不过标记了是EventListener。EventListener是一个标记,并无设定方法。
在netty中是如何使用的,咱们更多的是针对channel,能够以channel为例,来分析promise一些比较核心的用法。
首先有个接口,ChannelPromise,一样ChannelPromise返回的都是ChannelPromise,它继承ChannelFuture和Promise。
而后来看一下ChannelFuture的默认使用:DefaultChannelFuture
他继承自DefaultPromise,先看一下DefaultPromise:
先看addListener方法,addListener是一个动做,它须要作一些事情。
一个是添加进去,addListener0,添加进去确定是要作管理的,那如何管理,要么是容器要么是链表。
那这个里面,DefaultFutureListener里面是一个容器,一个数组,只不过是限定了类型。
addListener作了2件事,一个是作添加,添加完以后,就要作判断这个task是否已经结束了。jdk中的Future的一个核心方法之一就是isDone().人物的结束与否并非看你是否返回告终果,而是看isDone,因此在作任何事以前,先判断是否isDone。假如结束以后就notifyListeners(),之因此说addListener它是一个回调,是由于notifyListeners能够拿到一个executer,而后作事情。
对listener进行遍历,而后执行。咱们管理了一个针对Future的动做。
监听器就是一个回调,只不过作了相应的封装。
因此在添加listener的时候,必定要注意有一个isDone的判断。
看一下DefaultPromise的isDone():
假如咱们并无设置值的话,result就是null,他只不过传入了一个Object。它并无限定类型,能够放DefaultPromise的V类型,一样也能够只是一个Object,管理几种装态,这个isDone只是表明结束了,并非表明成功了。
isDone以后,须要作isSuccess的判断。那isSuccess应该放在哪一块去作呢?
仍是看DefaultPromise:
默认状况下它是成功或者有值的。
而后来看一下DefaultChannelFuture的setSuccess方法:
setSuccess为null,而后trySuccess也是null。
若是你传的是null,就设置为SUCCESS.设置完以后就是一个通知的回调。
而后看一下他们常见的调用:
设置为success状态以后返回,在使用的时候只须要点addListener便可,就直接去执行listener中的动做了。
pool.acquire()已经把success设置进去了,因此只须要addListener便可。他的isDone就结束了。因此addLIstener就直接去执行相关的代码了。
一样的,获取链接也是先去判断是否isDone,结束了的话,就作结束以后的动做,
首先我本身定义了一个promise,你拿到这个channel,放到这个promise里面,外层的话,就能够作到一个控制。在这一起,直接加一个listener就好了。用的就是netty的一向的套路。
在使用future的使用,经过这种方式,咱们学会使用addListener,咱们要指导addListener要通过哪些操做,第一步添加,第二步,经过isDone判断是否结束了,结束了的话,就作一些事,isDone后面紧跟的就是isSuccess,我是否是成功设定了,成功了的话,我才会去取。假如失败的话,就tryFuture,若是有异常的话,就future.cause().
接着咱们在看一下其余的代码,
config().group().register(channel)获得一个ChannelFuture,若是要判断isDone,再判断isSuccess,不如直接判断cause()是否为null,不为null,再判断是否注册了,没有注册成功的话,就close,没有异常直接返回去,不会作任何其余的动做。
学过nio的就应该知道,注册其实仍是要经过channel.register()来实现。
它经过ChannelPromise把Channel包裹进来,而后它就能够拿到当前的selector,
因此能够把promise当作一个针对channel的动做。