vertx的Future模式的实现FutureImpl分析

问题

在使用异步编程的时候,Future模式实现需要注意几个问题:

  • 当提前已经Complete,但是还没有设置Handler,这时候需要在设置Handler的时候执行Handler方法
  • 当提前已经设置了Handler,在执行Complete方法的时候,需要执行Handler方法

解决

其实,只要在Complete方法里面判断当前有没有设置Handler,如果设置了,那就执行Handler,如果没有,就没有,然后在设置Handler方法里面判断当前有没有执行完成,如果执行完成,那就直接执行Handler,如果没有,就没有…当然,执行的时候要考虑线程安全问题,我们可以直接使用synchronized关键字来进行线程安全问题处理,因为在1.8之后性能也不是很低…

我们看vert.x里面的Future的具体实现

首先我们看Future的实现:
在这里插入图片描述
有个叫FutureImpl,应该就是具体的简单实现,当然,我们也可以直接实现,然后使用自己封装的Futrure去完成需求,当然,如果有一些定制的需求,建议直接继承FutureImpl,去重写对应方法好了…
线看一看属性:
在这里插入图片描述
比较简单,就是是否成功,失败,设置的Handler,结果和异常信息…

先看isComplete方法,

在这里插入图片描述
如果不使用两个属性,成功失败,会造成什么情况,默认都是false,我就不知道,到底是失败了还是没有执行…如果执行失败那么failed会是true,
在这里插入图片描述

再看setHandler方法

按照我们刚才说的,setHandler,只需要判断将当前handler设置进去,然后判断有没有执行成功,如果执行成功了,那就执行当前Handler,如果没有,就不管:

/**
   * Set a handler for the result. It will get called when it's complete
   */
  public Future<T> setHandler(Handler<AsyncResult<T>> handler) {
    boolean callHandler;
    //防止线程安全问题...
    synchronized (this) {
      this.handler = handler;
      	// 可能会在此刻,去执行setHandler方法
      callHandler = isComplete();
    }
    if (callHandler) {
      handler.handle(this);
    }
    return this;
  }

再看complete方法

在这里插入图片描述
就是tryComplete方法:我们完成只需要将结果赋值进去,然后判断当前Handler有没有设置,如果设置了,那就执行,如果没有设置那就直接返回.
源码如下:

  @Override
  public boolean tryComplete(T result) {
    Handler<AsyncResult<T>> h;
    //线程安全问题
    synchronized (this) {
    //如果已经执行完成,那就直接返回,并抛出异常
      if (succeeded || failed) {
        return false;
      }
      this.result = result;
      succeeded = true;
      	// 可能会在此刻,去执行setHandler方法,下面还没有执行
      h = handler;
    }
    if (h != null) {
      h.handle(this);
    }
    return true;
  }

如果.没有使用synchronized加锁,会造成什么问题?

在setHandler的时候,如果当设置完成Handler,线程切出去执行complete方法,这时候会执行两次Handler;
在complete的时候,如果刚把成功状态改为成功,还没有进行Handler的赋值的时候,去执行setHandler,这时候也会执行两次Handler,就会导致线程安全问题.

posted @ 2020-05-05 16:19  你就像甜甜的益达  阅读(176)  评论(0编辑  收藏  举报