Netty的深入浅出--41.并发中的Future和Netty中的Future分
我们继续分析netty的bind方法
上一章说到,调用bind方法才正在启动了服务端
上一章中说到,这章将会重点介绍Future和ChannelFuture两个方法:
首先分析future这个父接口:
进入到并发包中的Future:
对于它的方法基本上看名字就能看懂
简单描述:Future表示的是异步计算返回的结果
它里面的方法主要完成三个任务:
检查计算是否完成;
等待计算;
获取计算机结果;
计算结果只能通过get来获取
而且get方法本身是会阻塞的,直到获取到
取消这个操作是通过cancel来完成的
还提供了一些额外的方法来判断是否它是正常取消还是执行cancel方法取消的
如果future已经计算出结果了就不能被取消
如果你想要使用一个future的目的是取消,而且它并没有提供一个有用的结果(因上一句话说了,只要返回了结果就不能取消),那你可以声明一个future<?>的类型,并且返回一个null作为结果:
简单实例:
callable方法实际是丢给一个线程池来执行,然后主线程可以去执行其他事情(displayOtherThings();)。到后面我们通过future.get()方法来获取到它的返回值。
然后有一个futureTask类继承了Future类也继承了runnable,而且它可以通过Executor来执行。
上面那种方式可以通过下面这种方式替换掉:
计算这个动作一定是发送在get()方法之前的:
总结性的来说:future通过异步的方法,计算出结果,然后通过get方法以阻塞的方式来获取结果。
cancel方法尝试着取消任务的执行。
说明了几种取消失败的可能:
1.任务已经完成;2.任务已经被取消;
取消成功的几种可能:
1.这个任务没有开始;2.这个任务没有运行;
如果这个任务已经开始了,如何要取消的话,是通过mayInterruptIfRunning决定的:
只要是结束了都返回true:
现在关于并发的future已经分析完毕,现在回到netty的future进行分析:
netty中的future直接继承了并发包中的future
简单描述:表示的是异步操作的结果
addListener()方法:
这里面用到了一种观察者设计模式。
当future完成的之后,listener就会收到通知。
添加的listener是GenericFutureListener
它也是一个接口:简单描述就是这个GenericFutureListener通过addListener()方法添加进去。监听着Future的结果,一旦GenericFutureListener通过addListener()方法添加进去之后,异步的操作结果(Future的结果)就会被通知。
在传入的Future执行完成之后,该方法OperationComplete就会被调用
addListener()的重载方法,“..."是一个可变参数,简单来说就是传入多个listeners
sync()方法想必大家还记得吧,在bind()方法后面调用的
等待future完成,如果future失败了就会抛出失败的原因。
syncUniterruptibly()和上面那个sync()方法一样的;
await()方法是等待完成,但是如果出现问题不抛出异常。
现在我们对比一下,并发包提供的future和netty继承下来 重写的future有什么区别:
主要原因在于并发包concurrent下面的get()方法是阻塞的,由于实现的是callable接口,call()方法是异步的,所以对于get()方法到底什么时候执行对于程序员来说根本不知道。所以这就是一个很尴尬的问题。
对于netty并发包里面的future来说,它是通过GenericFutureListener对象里面的方法来实现的
而operationComplete()方法是通过future的任务完成之后自动调用的,相当于针对的是future对象。
总结来说:并发布concurrent中的future对象是通过被动的调用get方法来实现结果的返回,而netty中通过监听事件,当事件结束之后,自动调用operationComplete()方法获取返回值。
而且在concurrent包下的future的isDone()方法不管是正常终止还是异常终止,都会返回true,这样的话你根本不知道它是为什么抛出异常。
而netty包下的future就不同了,它只有I/O操作正在完成了之后才会返回true。
总结来说:Future对象是对传入的channel进行操作,然后返回操作结果