Future和Promise

1、Future功能

Future最早来源于java.util.concurrent.Future,用于代表异步操作的结果。

可以通过get方法获取操作结果,如果操作尚未完成,则会同步阻塞当前调用的线程;如果不允许阻塞太长时间或者无限期阻塞,可以通过带超时时间的get获取结果;如果达到超时时间你操作仍然没有完成,则抛出TimeoutException。

可以通过isDone方法可以判断当前的异步操作是否完成,如果完成,无论成功与否,都返回true,否则返回false。

可以通过cancel尝试取消异步操作。

 

2、ChannelFuture功能介绍

netty中,所有I/O操作都是异步的。存在的问题:调用者如何获取异步操作的结果?ChannelFuture就是为解决这个问题而设计的。

ChannelFuture有两种状态:uncompleted和completed。当开始一个I/O操作时,一个新的ChannelFuture被创建,此时它处于uncompleted状态——非失败、非成功、非取消,因为I/O操作此时还没有完成。一旦完成,ChannelFuture将会被设置成completed。

当I/O操作完成之后,I/O线程会回到ChannelFuture中GenericFutureListener的operationComplete方法,并把ChannelFuture对象当做方法的入参。如果用户需要做上下文相关的操作,需要将上下文信息保存到对应的ChannelFuture中。

推荐通过GenericFutureListener代替ChannelFuture的get等方法的原因是:当我们进行一步I/O操作时,完成的时间是无法预测的,如果不设置超时时间,他会导致调用线程长时间被阻塞,甚至挂死。而设置超时时间,时间又无法精确预测。利用异步通知机制回调GenericFutureListener是最佳解决方案。

需要注意的是,不要再ChannelFuture中调用ChannelFuture的await方法,这会导致死锁。原因是发起I/O操作之后,由I/O线程负责异步通知发起I/O操作的用户线程,如果I/O线程和用户线程是同一线程,就会导致I/O线程等待自己通知操作完成,这就导致死锁,即自己把自己挂死。

异步I/O操作有两类超时:一个是TCP层面的I/O超时,另一个是业务逻辑层面的操作超时。

3、ChannelFuture源码分析

  • AbstractFuture

 

调用await方法进行无限期阻塞,当I/O操作完成后会被notify()。程序继续向下执行,检查I/O操作是否发生了异常,如果异常,则getNow获取结果并返回。否则,将异常堆栈进行包装,抛出ExecutionException。

4、Promise功能介绍

是可写的Future,Future本身并没有写操作相关的接口,Netty通过Promis对Future进行扩展,用于设置I/O操作的结果。

5、Promise继承关系图

 

6、Promise源码分析

DefaultPromise Promise<V> setSuccess(V result);

  1. 调用setSuccess0方法并对其操作结果判断,如果失败抛出IllegalStateException

    1. 判断Promise的操作结果是否已经被设置,如果是,则不允许重复设置,返回设置失败
    2. 如果没有被设置,由于可能存在I/O线程和用户线程同时操作Promise,所以设置操作结果的时候需要加锁保护,防止并发。
    3. 对操作结果是否被设置进行二次判断,如果被设置返回失败
    4. 对操作结果result进行判断,如果为空,说明仅仅需要notify在等待的业务线程,不包含具体的业务逻辑对象。因此,将result设置为系统默认的SUCCESS。如果操作结果非空,将结果设置为result
    5. 如果有正在等待异步I/O操作完成的用户线程或者其他系统线程,则调用nitifyAll方法环形所有正在等待的线程。注意,notifyAll和wait都必须在同步块内使用
  2. 如果成功,则调用notifyListeners通知

由于在I/O线程中调用Promise的await或者sync会导致死锁,所以在循环体中需要对死锁进行保护性校验,防止I/O线程被挂死,最后调用java.lang.Object.wait()方法进行无线期等待,知道I/O线程调用setSuccess方法,trySuccess方法,setFailure或者tryFailure方法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值